How to Make my Powershell script discover a Desktop on my network and delete user profiles remotely - powershell

I am fairly new with powershell scripting and trying to learn. I am trying to create a PS1 file that runs with a GUI for easy use for other people on my team, that can delete profiles off of a Desktop/Laptop remotely. I have a script below that works for local profiles and would like to enhance it for remote PC's so we dont physically have to collect devices when cleaning up desktops/laptops that are filled with profiles. These computers have a program that runs that refreshes the profiles daily so a script that cleans based on days since last log in will not work.
If (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
$arguments = "& '" + $myinvocation.mycommand.definition + "'"
Start-Process powershell -Verb runAs -ArgumentList $arguments
Break
}
Add-Type -AssemblyName System.Windows.Forms
$form = New-Object System.Windows.Forms.Form
$form.Size = New-Object System.Drawing.Size(400,300)
$form.Text = "Delete User Profiles"
$form.StartPosition = [System.Windows.Forms.FormStartPosition]::CenterScreen
$listBox = New-Object System.Windows.Forms.ListBox
$listBox.Size = New-Object System.Drawing.Size(360,200)
$listBox.Location = New-Object System.Drawing.Point(20,20)
$listBox.SelectionMode = [System.Windows.Forms.SelectionMode]::MultiSimple
$userProfiles = Get-ciminstance -classname Win32_UserProfile
foreach ($userProfile in $userProfiles) {
if (($userProfile.localpath -notmatch "Public") -and ($userProfile.localpath -notmatch "Default")) {
$listBox.Items.Add($userProfile.localpath)
}
}
$form.Controls.Add($listBox)
$deleteButton = New-Object System.Windows.Forms.Button
$deleteButton.Size = New-Object System.Drawing.Size(100,30)
$deleteButton.Location = New-Object System.Drawing.Point(20,230)
$deleteButton.Text = "Delete"
$deleteButton.Add_Click({
foreach ($item in $listBox.SelectedItems) {
##Remove-Item -Path "$item" -Recurse -Force
##Properly removing item from WMI. note: -whatif currently specified so the operation doesn't actually occur
get-ciminstance -classname win32_userprofile | where-object -property localpath -like $item | remove-ciminstance ##-whatif
}
[System.Windows.Forms.MessageBox]::Show("Done","Delete Dialog",[Windows.Forms.MessageBoxButtons]::OkCancel)
})
$form.Controls.Add($deleteButton)
#$form.Controls.Add($listBox)
$showButton = New-Object System.Windows.Forms.Button
$showButton.Size = New-Object System.Drawing.Size(100,30)
$showButton.Location = New-Object System.Drawing.Point(140,230)
$showButton.Text = "Refresh"# "Show"
$showButton.Add_Click({
# foreach ($item in $listBox.SelectedItems) {
# [System.Windows.Forms.MessageBox]::Show("You have chosen to remove $item","Profile Selection Dialog",[Windows.Forms.MessageBoxButtons]::OkCancel)
# }
$listBox.Items.Clear()
$userProfiles = Get-ciminstance -classname Win32_UserProfile
foreach ($userProfile in $userProfiles) {
if (($userProfile.localpath -notmatch "Public") -and ($userProfile.localpath -notmatch "Default")) {
$listBox.Items.Add($userProfile.localpath)
}
}
})
$form.Controls.Add($showButton)
$form.ShowDialog()
Please Help.........

Related

unattended software installation using PowerShell GUI

I want to create a GUI using PowerShell, that will allow users to select software to install. The software will be installed using unattended (silent) options, so the user doesn't have to do anything more that select the desired software, and click OK.
Since the installation is silent and there will be plenty of software to install, I want to give some feedback to the user, as to the status of the installation. So I put a textbox showing which software have been installed and which software is currently installing.
My problem is that all the text appears at the same time in the textbox and it also looks messy.
I want it to be like this:
installing 7-zip...OK
installing notepad ++...OK
installing visual studio code...OK
This is the script
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
# software name
$software1 = "7-Zip"
$software2 = "Notepad++"
$software3 = "Visual Studio Code"
# installation status
$software1status = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Where {$_.DisplayName -like "*$software1*"}
$software2status = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Where {$_.DisplayName -like "*$software2*"}
$software3status = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Where {$_.DisplayName -like "*$software3*"}
# set form size
$Form = New-Object System.Windows.Forms.Form
$Form.width = 500
$Form.height = 500
$Form.Text = 'Install Software'
# set font
$Font = New-Object System.Drawing.Font("Verdana",10)
$Form.Font = $Font
# results textbox
$ResultsTextBox = New-Object System.Windows.Forms.TextBox
$ResultsTextBox.Location = New-Object System.Drawing.Size(200,30)
$ResultsTextBox.Size = New-Object System.Drawing.Size(250,350)
$ResultsTextBox.Multiline = $true
$ResultsTextBox.Text = "make your selections on the left"
$Form.Controls.Add($ResultsTextBox)
# checkbox software1
$checkbox1 = new-object System.Windows.Forms.checkbox
$checkbox1.Location = new-object System.Drawing.Size(30,30)
$checkbox1.Size = new-object System.Drawing.Size(120,20)
$checkbox1.Text = "$software1"
if ($software1status -eq $null) {$checkbox1.Checked = $false} Else {$checkbox1.Checked = $true}
$Form.Controls.Add($checkbox1)
# checkbox software2
$checkbox2 = new-object System.Windows.Forms.checkbox
$checkbox2.Location = new-object System.Drawing.Size(30,50)
$checkbox2.Size = new-object System.Drawing.Size(120,20)
$checkbox2.Text = "$software2"
if ($software2status -eq $null) {$checkbox2.Checked = $false} Else {$checkbox2.Checked = $true}
$Form.Controls.Add($checkbox2)
# checkbox software3
$checkbox3 = new-object System.Windows.Forms.checkbox
$checkbox3.Location = new-object System.Drawing.Size(30,70)
$checkbox3.Size = new-object System.Drawing.Size(120,20)
$checkbox3.Text = "$software3"
if ($software3status -eq $null) {$checkbox3.Checked = $false} Else {$checkbox3.Checked = $true}
$Form.Controls.Add($checkbox3)
# ok button
$OKButton = new-object System.Windows.Forms.Button
$OKButton.Location = new-object System.Drawing.Size(130,400)
$OKButton.Size = new-object System.Drawing.Size(100,40)
$OKButton.Text = "OK"
$Form.Controls.Add($OKButton)
# close button
$CloseButton = new-object System.Windows.Forms.Button
$CloseButton.Location = new-object System.Drawing.Size(255,400)
$CloseButton.Size = new-object System.Drawing.Size(100,40)
$CloseButton.Text = "Close"
$CloseButton.Add_Click({$Form.Close()})
$Form.Controls.Add($CloseButton)
$OKButton.Add_Click{
if($checkbox1.Checked -and $software1status -eq $null) {Start-Process -FilePath $PSScriptRoot\software\7z1900-x64.msi /passive ; $ResultsTextBox.Text += "installing 7-zip"}
if($checkbox1.Checked -eq $false -and $software1status -ne $null ) {Start-Process MsiExec.exe "/x{23170F69-40C1-2702-1900-000001000000} /passive" ; $ResultsTextBox.Text += "removing 7-zip"}
if($checkbox2.Checked -and $software2status -eq $null) {Start-Process -FilePath $PSScriptRoot\software\npp.7.8.1.Installer.x64.exe /S ; $ResultsTextBox.Text += "installing notepad ++"}
if($checkbox2.Checked -eq $false -and $software2status -ne $null ) {Start-Process -FilePath "${env:ProgramFiles}\Notepad++\uninstall.exe" /S ; $ResultsTextBox.Text += "removing notepad ++"}
if($checkbox3.Checked -and $software3status -eq $null) {Start-Process -FilePath $PSScriptRoot\software\VSCodeSetup-x64-1.40.2.exe "/SILENT /NORESTART /MERGETASKS=!runcode" ; $ResultsTextBox.Text += "installing visual studio code"}
if($checkbox3.Checked -eq $false -and $software3status -ne $null ) {Start-Process -FilePath "${env:ProgramFiles}\Microsoft VS Code\unins000.exe" /SILENT ; $ResultsTextBox.Text += "removing visual studio code"}
}
# activate form
$Form.Add_Shown({$Form.Activate()})
[void] $Form.ShowDialog()
Use AppendText instead. you need to send carriage returns and new line characters also using that method:
$ResultsTextBox.AppendText("`r`nInstalling new file...")
However, you can only do things like this during an event like a button click. If you want to update more often you need to create events for that.

Limiting Scope Powershell

So i've been playing around with this script to audit file server folder ACL's, and it works great, just returning too much data. What i was hoping i could do is filter out the folders where there are no special permissions than the parent folder, I think this would help me reduce the amount of entries into my table and allow me to manipulate it into something more readable. Basically only return the parent ACL and any child object that doesn't inherit from parent or has special permissions.
$connectionString = "Server=KCC-RPT-Admin\SQLEXPRESS;Database=Audit;User ID=report_admin; Password=Payday!5;"
$tableName = "FilePermissions"
function WriteSQL ($query)
{
if ($debug -eq $true) {Write-Host $query}
$Connection = New-Object System.Data.SqlClient.SqlConnection
$Connection.ConnectionString = $connectionString
$Connection.Open()
$Command = New-Object System.Data.SqlClient.SqlCommand
$command.Connection = $Connection
$command.CommandText = $query
$command.ExecuteNonQuery()
$connection.Close()
}
$ErrorActionPreference = "Continue"
$strComputer = $env:ComputerName
$colDrives = Get-PSDrive -PSProvider Filesystem
ForEach ($DriveLetter in $colDrives) {
$StartPath = "E:\Share\"
Get-ChildItem -LiteralPath $StartPath -Recurse -Directory |
ForEach {
$FullPath = Get-Item -LiteralPath (Get-Item -LiteralPath $_.PSPath)
(Get-Item -LiteralPath $FullPath).GetAccessControl() |
Select * -Expand Access |
Select #{N='ServerName';E={$strComputer}},
#{N='FullPath';E={$FullPath}},
#{N='Type';E={If($FullPath.PSIsContainer -eq $True) {'D'} Else {'F'}}},
#{N='Owner';E={$_.Owner}},
#{N='Trustee';E={$_.IdentityReference}},
#{N='Inherited';E={$_.IsInherited}},
#{N='InheritanceFlags';E={$_.InheritanceFlags}},
#{N='AceFlag';E={$_.PropagationFlags}},
#{N='AceType';E={$_.AccessControlType}},
#{N='AccessMasks';E={$_.FileSystemRights}} } |
%{
$query = "INSERT INTO $tableName (servername,fullpath,type,owner,trustee,inherited,inheritanceflags,aceflag,acetype,accessmasks) VALUES ('$($_.servername)','$($_.fullpath)','$($_.type)','$($_.owner)','$($_.trustee)','$($_.inherited)','$($_.inheritanceflags)','$($_.aceflag)','$($_.acetype)','$($_.accessmasks)')"
WriteSQL $query
}
}

Login to another domain from powershell

I wrote a script to logout the citrix user and it is working fine, if I am accessing it with same domain, but if I try to run that script from some other computer where the local domain is different from the one citrix connects to it is failing, please let me know how I can connect to the citrix domain from the other local domain.
To give context I am attaching the code below,
Please help.
Regards,
AVs
Code:
# Import the Active Directory module for the Get-ADComputer CmdLet
Import-Module ActiveDirectory
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
#Form to take username and password
$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = "Citrix User Session Disconnection"
$objForm.Size = New-Object System.Drawing.Size(300,200)
$objForm.StartPosition = "CenterScreen"
#Data Label
$Label = New-Object System.Windows.Forms.Label
$Label.Location = New-Object System.Drawing.Size(10,130)
$Label.Size = New-Object System.Drawing.Size(250,150)
$Label.ForeColor = "White"
$Label.BackColor = "Blue"
$Label.Text = "***Give your Citrix username and password to logoff the user from the server.***"
$objForm.Controls.Add($Label)
#Username Label
$userLabel = New-Object System.Windows.Forms.Label
$userLabel.Location = New-Object System.Drawing.Size(10,20)
$userLabel.Size = New-Object System.Drawing.Size(80,30)
$userLabel.Text = "User Name"
$objForm.Controls.Add($userLabel)
#Username Textbox
$userTextBox = New-Object System.Windows.Forms.TextBox
$userTextBox.Location = New-Object System.Drawing.Size(130,20)
$userTextBox.Size = New-Object System.Drawing.Size(150,20)
$objForm.Controls.Add($userTextBox)
#Password Label
$PassLabel = New-Object System.Windows.Forms.Label
$PassLabel.Location = New-Object System.Drawing.Size(10,60)
$PassLabel.Size = New-Object System.Drawing.Size(80,30)
$PassLabel.Text = "Password"
$objForm.Controls.Add($PassLabel)
#Password Textbox
$PassTextBox2 = New-Object System.Windows.Forms.MaskedTextBox
$PassTextBox2.PasswordChar = '*'
$PassTextBox2.Location = New-Object System.Drawing.Size(130,60)
$PassTextBox2.Size = New-Object System.Drawing.Size(150,20)
$objForm.Controls.Add($PassTextBox2)
#Disconnect Button
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(200,100)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.ForeColor = "Red"
$OKButton.Text = "Disconnect"
$OKButton.Add_Click({$username=$userTextBox.Text;$objForm.Close()})
$OKButton.Add_Click({$Password=$PassTextBox2.Text;$objForm.Close()})
$objForm.Controls.Add($OKButton)
$objForm.ShowDialog()
Read-Host "DOMAIN\USERNAME" -AsSecureString | ConvertFrom-SecureString | Out-File C:\SecureData\SecureString.txt
#SharePoint Admin Account
$SPAdmin = "DOMAIN\ADMIN"
$Password = Get-Content C:\SecureDate\securestring.txt | convertto-securestring
$Credential = new-object -typename System.Management.Automation.PSCredential -argumentlist $SPAdmin, $Password
Get-WmiObject -Class Win32_Service -ComputerName "Server" -Filter "Name='ServiceName'" -Credential $Credential
#Authenticaton
$Domain = $env:USERDOMAIN
$ct = [System.DirectoryServices.AccountManagement.ContextType]::Domain
$pc = New-Object System.DirectoryServices.AccountManagement.PrincipalContext $ct,$Domain
$auth = $pc.ValidateCredentials($userName,$Password)
# Get today's date for the report
$today = Get-Date
#Setup email parameters
#$subject = "ACTIVE SERVER SESSIONS REPORT - " + $today
#$priority = "Normal"
#$smtpServer = "mail.itechnologies.com.au"
#$emailFrom = "rayithy#itechnologies.com.au"
#$emailTo = "rayithy#itechnologies.com.au"
# Create a fresh variable to collect the results. You can use this to output as desired
$SessionList = "ACTIVE SERVER SESSIONS REPORT - " + $today + "`n`n"
# Query Active Directory for computers running a Server operating system
#$Servers = Get-ADComputer -Filter {OperatingSystem -like "*server*"}
$Servers = Import-Csv C:\powershell\Test.csv
if ($auth -eq "True")
{
# Loop through the list to query each server for login sessions
ForEach ($Server in $Servers) {
$ServerName = $Server.Name
# When running interactively, uncomment the Write-Host line below to show which server is being queried
# Write-Host "Querying $ServerName"
# Run the qwinsta.exe and parse the output
$queryResults = (qwinsta /SERVER:$ServerName | foreach { (($_.trim() -replace "\s+",","))} | ConvertFrom-Csv)
# Pull the session information from each instance
ForEach ($queryResult in $queryResults) {
$RDPUser = $queryResult.USERNAME
$sessionType = $queryResult.SESSIONNAME
# We only want to display where a "person" is logged in. Otherwise unused sessions show up as USERNAME as a number
If (($RDPUser -match $username) -and ($RDPUser -ne $NULL)) {
# When running interactively, uncomment the Write-Host line below to show the output to screen
# Write-Host $ServerName logged in by $RDPUser on $sessionType
$SessionList = $SessionList + "`n`n" + $ServerName + " logged in by " + $RDPUser + " on " + $sessionType
logoff $sessionType /server:$ServerName
Write-Host $RDPUser "LoggedOff"
}
}
}
}
else {
$Font = New-Object System.Drawing.Font("Times New Roman",14,[System.Drawing.FontStyle]::Italic)
#Form to display the error
$objForm2 = New-Object System.Windows.Forms.Form
$objForm2.Text = "Citrix User Session Disconnection"
$objForm2.Size = New-Object System.Drawing.Size(300,200)
$objForm2.StartPosition = "CenterScreen"
$objForm2.BackColor = "Yellow"
#Error message
$errorLabel = New-Object System.Windows.Forms.Label
$errorLabel.Location = New-Object System.Drawing.Size(10,20)
$errorLabel.Size = New-Object System.Drawing.Size(250,150)
$errorLabel.Text = "'Username/Password is not correct' Or 'User Not Logged in the Server'"
$errorLabel.Font = $Font
$errorLabel.forecolor = "Red"
$objForm2.Controls.Add($errorLabel)
$objForm2.ShowDialog()
}
In the Authentication section of your script:
#Authenticaton
$Domain = $env:USERDOMAIN
$ct = [System.DirectoryServices.AccountManagement.ContextType]::Domain
$pc = New-Object System.DirectoryServices.AccountManagement.PrincipalContext $ct,$Domain
$auth = $pc.ValidateCredentials($userName,$Password)
You're passing in $Domain as the current user's Domain. If you modify this to specify the domain Citrix auths against, you should be able to connect

Powershell script works in ISE but not in Run With Powershell

I had develop a script that basically restart a service in a remove server based on a selection.
This selection is done by a form.
The problem is... when I run this using the ISE... the script work totally fine.
When I run this using the RIGHT CLICK / RUN with Powershell
My form doesn't work. The Button that I had created didn't appear...
What can be wrong?
Here is my code:
Function Write-Centered {
Param( [string] $message,
[string] $color = "black")
$offsetvalue = [Math]::Round(([Console]::WindowWidth / 2) + ($message.Length / 2))
Write-Host ("{0,$offsetvalue}" -f $message) -ForegroundColor $color
}
clear
$timestamp=Get-date -format yyyy_MM_dd_hh_mm_ss
$systems = #(
("System 1","Server1","bmc_ctsa_sm_SAP_Instance_2"),
("System 2","Server2","bmc_ctsa_sm_SAP_Instance_6"),
("System 3","Server3","bmc_ctsa_sm_SAP_Instance_6")
)
Write-Centered "Service Restart Tool" "Green"
Write-Centered "Choose the target system you would like to restart" "Green"
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
$Form1 = New-Object System.Windows.Forms.Form
$Form1.ClientSize = New-Object System.Drawing.Size(300, 100)
$form1.topmost = $true
$Form1.Controls.Add($Button)
$Form1.Text = "SSPR Restart Tool"
$Button = New-Object System.Windows.Forms.Button
$Button.Location = New-Object System.Drawing.Point(150, 25)
$Button.Size = New-Object System.Drawing.Size(120, 25)
$Button.add_Click({
$label.Text = $comboBox1.SelectedItem.ToString()
$Form1.Close()
})
$Button.Text = "Start Process"
$Label = New-Object System.Windows.Forms.Label
$Label.Location = New-Object System.Drawing.Point(10, 10)
$Label.Size = New-Object System.Drawing.Size(300, 15)
$Label.Text = "Please select the system you would like to restart"
$Form1.Controls.Add($Label)
$comboBox1 = New-Object System.Windows.Forms.ComboBox
$comboBox1.Location = New-Object System.Drawing.Point(10, 25)
$comboBox1.Size = New-Object System.Drawing.Size(120, 25)
foreach($system in $systems)
{
$comboBox1.Items.add($system[0]) | Out-Null
}
$Form1.Controls.Add($comboBox1)
$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(70, 90)
$label.Size = New-Object System.Drawing.Size(98, 23)
$label.Text = ""
$Form1.Controls.Add($label)
[void]$form1.showdialog()
Write-Centered $comboBox1.Text "Yellow"
$do=0
$i=0
do {
if ($comboBox1.Text -eq $systems[$i][0]){
$result=$i
$i++
}
$do++
}while ($do -le $systems.length-1)
$System=$systems[$result][0]
$Server=$systems[$result][1]
$Instance=$systems[$result][2]
$yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", `
"Start the process."
$no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", `
"Cancel the process."
$options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
$result = $host.ui.PromptForChoice("",`
"`nWould you like to progress with the service restart? `n`nSystem: $System`nServer: $Server`nInstance: $Instance", $options, 0)
if ($result -eq 0) {
$services = Get-Service -computername $Server -name $Instance
$target=$services.name
$sharefolder = "\\"+$Server+"\c$"
New-PSDrive –Name “X” –PSProvider FileSystem –Root $sharefolder | out-null
Write-Host ======================================================
Write-Host = Searching for the destination folder. Please wait...
Write-Host ======================================================
$test1=Test-Path "X:\Program Files (x86)\BMC Software"
$test2=Test-Path "X:\Program Files\BMC Software"
if ($test1) {
$file=Get-ChildItem "X:\Program Files (x86)\BMC Software" -recurse | Where-Object {$_.PSIsContainer -eq $true -and $_.Name -match "CONTROL-SA"}
} elseif ($test2){
$file=Get-ChildItem "X:\Program Files\BMC Software" -recurse | Where-Object {$_.PSIsContainer -eq $true -and $_.Name -match "CONTROL-SA"}
}
$fullname=$file.FullName+"\Services Manager\"+$Instance
$fullname
Write-Host ======================================================
Write-Host = Stopping $target
Write-Host ======================================================
Get-Service -Name $target -ComputerName $Server | Set-Service -Status Stopped
$src=$fullname+"\log\*"
$des=$fullname+"\log_bkp_"+$timestamp+"\"
Write-Host ======================================================
Write-Host = Perform LOG folder backup for troubleshooting
Write-Host ======================================================
New-Item $des -type directory | out-null
Move-item -path $src -destination $des -force -verbose
#Remove-item $src -force -recurse -verbose
Get-Service -Name $target -ComputerName $Server | Set-Service -Status Running
Remove-PSDrive -Name "X" | out-null
}
elseif ($result -eq 1) {
BREAK
}
Write-Host ======================================================
Write-Host = Process Completed
Write-Host = You may now close this window
Write-Host ======================================================
Start-Sleep -s 120
Have the screen captures of the results.. but low reputation prevent me to post it... :-(
I typo'd my comment, it should be Controls and not Controles, but that's the issue. After $Form1.Controls.Add($label) add a new line:
$Form1.Controls.Add($Button)
See if it doesn't work as expected at that time. It does for me when I tested it.
A wrong place for the $Form1.Controls.Add($Button) was preventing my code to show up the control button...
Thanks for the hint

How to troubleshoot "Get-WmiObject : Access is denied."?

I have two working powershell scripts. You would invoke script1.ps1 with:
.\script1.ps1 "sender-ip=10.10.10.10"
And the script is supposed to return userId=DOMAIN/UserId. The first script:
#script1.ps1
$abc = $args
$startInfo = $NULL
$process = $NULL
$standardOut = $NULL
<#Previously created password file in C:\Script\cred.txt, read-host -assecurestring | convertfrom-securestring | out-file C:\Script\cred.txt#>
$password = get-content C:\Script\cred.txt | convertto-securestring
$startInfo = New-Object System.Diagnostics.ProcessStartInfo
$startInfo.FileName = "powershell.exe"
$startInfo.Arguments = "C:\script\script2.ps1 " + $abc
$startInfo.RedirectStandardOutput = $true
$startInfo.UseShellExecute = $false
$startInfo.CreateNoWindow = $false
$startInfo.Username = "Username"
$startInfo.Domain = "DOMAIN"
$startInfo.Password = $password
$process = New-Object System.Diagnostics.Process
$process.StartInfo = $startInfo
$process.Start() | Out-Null
$standardOut = $process.StandardOutput.ReadToEnd()
$process.WaitForExit()
# $standardOut should contain the results of "C:\script\script1.ps1"
$standardOut
And this is the entire working script2.ps1
#script2.ps1
$line_array = #()
$multi_array = #()
[hashtable]$my_hash = #{}
$Sender_IP = $NULL
$Win32OS = $NULL
$Build = $NULL
$LastUser = $NULL
$UserSID = $NULL
$userID=$NULL
$output = $NULL
foreach ($i in $args){
$line_array+= $i.split(" ")
}
foreach ($j in $line_array){
$multi_array += ,#($j.split("="))
}
foreach ($k in $multi_array){
$my_hash.add($k[0],$k[1])
}
$Sender_IP = $my_hash.Get_Item("sender-ip")
<#Gather information on the computer corresponding to $Sender_IP#>
$Win32OS = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $Sender_IP
<#Determine the build number#>
$Build = $Win32OS.BuildNumber
<#Running Windows Vista with SP1 and later, i.e. $Build is greater than or equal to 6001#>
if($Build -ge 6001){
$Win32User = Get-WmiObject -Class Win32_UserProfile -ComputerName $Sender_IP
$Win32User = $Win32User | Sort-Object -Property LastUseTime -Descending
$LastUser = $Win32User | Select-Object -First 1
$UserSID = New-Object System.Security.Principal.SecurityIdentifier($LastUser.SID)
$userId = $UserSID.Translate([System.Security.Principal.NTAccount])
$userId = $userId.Value
}
<#Running Windows Vista without SP1 and earlier, i.e $Build is less than or equal to 6000#>
elseif ($Build -le 6000){
$SysDrv = $Win32OS.SystemDrive
$SysDrv = $SysDrv.Replace(":","$")
$ProfDrv = "\\" + $Sender_IP + "\" + $SysDrv
$ProfLoc = Join-Path -Path $ProfDrv -ChildPath "Documents and Settings"
$Profiles = Get-ChildItem -Path $ProfLoc
$LastProf = $Profiles | ForEach-Object -Process {$_.GetFiles("ntuser.dat.LOG")}
$LastProf = $LastProf | Sort-Object -Property LastWriteTime -Descending | Select-Object -First 1
$userId = $LastProf.DirectoryName.Replace("$ProfLoc","").Trim("\").ToUpper()
}
else{
$userId = "Unknown/UserID"
}
if ($userId -ne $NULL){
$output = "userId=" + $userId
}
elseif ($userID -eq $NULL)
{
$userId = "Unknown/UserID"
$output = "userId=" + $userId
}
$output.replace("\","/")
Here is my problem. On most IP addresses in our domain, it returns:
Get-WmiObject : Access is denied. (Exception from HRESULT: 0x80070005
(E_ACCESS DENIED))
I researched this, and
"get-wmiobject win32_process -computername" gets error "Access denied , code 0x80070005" recommends giving the elevated account permission to run WMI throughout the Domain.
And this article, http://technet.microsoft.com/en-us/library/cc787533(v=ws.10).aspx explains how to do it.
But convincing the team that is in charge of the domain to grant WMI permissions to this elevated account will be a stretch. And, the script is able to return the UserId for some of the IP addresses in the domain.
Is there another way to resolve this? What should I research on google?
Have you considered using Invoke-Command and executing your script2 remotely using PowerShell Remoting?
Your remote script can the be executed using alternative credentials, you may have better luck convincing your security team to enable PowerShell Remoting rather than WMI. Your wmi queries when run via invoke-command will be local to the machine so will have a better chance of working, it also avoids the need to read the standard-out buffer.
To get you started, try Enter-PSSession as this will enable you to quickly determine how much work is necessary to get PS Remoting working in your environment.
In the future you might want to target many computers simultaneously, in which case PS Remoting and Start-Job would be helpful.