I've got the following parameter setup and trying to pass it into the 7zip password as the script shows. The Reason i've setup the parameter is I need passto contain the current month plus the rest of the password.
Script
$Password = $MonthFull+$year+"#Test"
Start-job -scriptblock {
param($p_output_zip_file, $p_exported_files)
Set-Alias SZ "C:\Program Files\7-Zip\7z.exe"
**SZ a $p_output_zip_file $p_exported_files -sdel -p'Jun2020#Test'** -- I need this to pick up the current month plus the rest of the password
} -name "Compress_File" -ArgumentList "$output_zip_file","$exported_files" | Out-Null
Thanks
$('-p' + ('{0:MMMyyyy}{1}' -f (Get-Date), '#Test'))
Related
I have a powershell script on machine A that uses PSSession to invoke a command on Machine B. Machine B has a powershell script which accepts 4 parameters. When I call this script with the 4 arguments as variables (which they MUST be), they are passed as empty strings/null. When I pass them as strings (For example -Argument1 "Hello"), that string will be passed as "Hello" and not as NULL/empty string.
Can anyone tell me why these are not passed correctly and how to fix it?
The powershell version on the client is 5.1.17134.112. The remote machine uses 5.1.14393.2248. These versions have been obtained by running $PSVersionTable.PSVersion.
The client is using Windows 10 Pro 10.0.17134. The server is using Windows 2016 Datacenter 10.0.14393 and is run as a VM on Azure.
I have tried using Script.ps1 -Argument1 $ClientArgument1 -Argument2 $ClientArgument2 ... to pass variables AND to use ArgumentList to pass the values comma separated to the script but both these attempts resulted in things not being printed.
I have noticed that when I use -Argument1 "Hello" -Argument2 $ClientArgument2 -Argument3 $ClientArgument3 -Argument4 $ClientArgument4, the Hello DOES get printed.
Code
Client that connects to the remote machine
$ErrorActionPreference = "Stop"
#Create credentials to log in
$URL = 'https://url.to.server:5986'
$Username = "username"
$pass = ConvertTo-SecureString -AsPlainText 'password' -Force
$SecureString = $pass
$MySecureCreds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Username,$SecureString
$ClientArgument1 = "Argument 1"
$ClientArgument2 = "Argument 2"
$ClientArgument3 = "Argument 3"
$ClientArgument4 = "Argument 4"
#Create the remote PS session
$sessionOption = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck
$session = New-PSSession -ConnectionUri $URL -Credential $MySecureCreds -SessionOption $sessionOption
#Call the remote script and pass variables
Invoke-Command -Session $session -Command {C:\Path\To\Script\On\Remote\Machine\Script.ps1 -Argument1 $ClientArgument1 -Argument2 $ClientArgument2 -Argument3 $ClientArgument3 -Argument4 $ClientArgument4}
#Note: Command is used because Command allows me to execute a script that is located on disk of the remote machine
The called script of the remote machine
param(
[String]$Argument1,
[String]$Argument2,
[String]$Argument3,
[String]$Argument4
)
Write-Host 'Results of the 4 parameters passed into this script:'
Write-Host $Argument1
Write-Host $Argument2
Write-Host $Argument3
Write-Host $Argument4
Write-Host "The results have been printed"
Expected and actual results
Expected results:
Results of the 4 parameters passed into this script:
Argument 1
Argument 2
Argument 3
Argument 4
The results have been printed
Actual results
Results of the 4 parameters passed into this script:
The results have been printed
Thank you very much for your time!
Since what inside the scriptblock in a different scope as the rest of your script, the $ClientArgument variables are undefined inside the scriptblock. The easiest solution if you are using PowerShell 3 or newer is to use the $using: scope. Otherwise an argumentlist for the Invoke-Command would be required.
Invoke-Command -Session $session -Command {C:\Path\To\Script\On\Remote\Machine\Script.ps1 -Argument1 $using:ClientArgument1 -Argument2 $using:ClientArgument2 -Argument3 $using:ClientArgument3 -Argument4 $using:ClientArgument4}
Try to execute it this way:
Invoke-Command -Session $session -Command {
C:\Path\To\Script\On\Remote\Machine\Script.ps1 `
-Argument1 $args[0] -Argument2 $args[1] `
-Argument3 $args[2] -Argument4 $args[3]
} -ArgumentList $ClientArgument1,$ClientArgument2,$ClientArgument3,$ClientArgument4
I am trying to automate a backup of an Azure database to my local machine using SQLPackage.exe. I am trying to add the date onto the filename so that every night it doesn't get overwritten.
The following line will pick up the date but will then stop the backup running with the error shown below
CMD
"C:\Program Files (x86)\Microsoft SQL Server\110\DAC\bin\sqlpackage.exe" /Action:Export /ssn:SERVER_NAME_HERE /sdn:DATABASE_NAME /su:USERNAME /sp:PASSWORD /tf:C:\Users\William\Desktop\BackupTest\BACKUPFILE'%date%'.bacpac
ERROR
*** Unrecognized command line argument '23/06/2017'.bacpac'.
I have tried using
+%date%+
+%date
And other options but no luck. Can anyone suggest anything?
More fundamentally, it is not recommend using bacpac to backup database. Bacpac is for load & move data in and out of Azure on demand.
SQLDB on Azure has backup service on by default so a scheduled backup is already provided by the service.
In addition, to properly make a bacpac, the database needs to be copied first then make a bacpac from the copy. Otherwise transactional consistency is not guaranteed and importing the bacpac can fail in the worst case.
You can add it using PowerShell as explained on below example.
Param(
[Parameter(Position=0,Mandatory=$true)]
[string]$ServerName
)
cls
try {
if((Get-PSSnapin -Name SQlServerCmdletSnapin100 -ErrorAction SilentlyContinue) -eq $null){
Add-PSSnapin SQlServerCmdletSnapin100
}
}
catch {
Write-Error "This script requires the SQLServerCmdletSnapIn100 snapin"
exit
}
$script_path = Split-Path -Parent $MyInvocation.MyCommand.Definition
$sql = "
SELECT name
FROM sys.databases
WHERE name NOT IN ('master', 'model', 'msdb', 'tempdb','distribution')
"
$data = Invoke-sqlcmd -Query $sql -ServerInstance $ServerName -Database master
$data | ForEach-Object {
$DatabaseName = $_.name
$now=get-Date
#
# Run sqlpackage
#
&"C:\Program Files (x86)\Microsoft SQL Server\110\DAC\bin\sqlpackage.exe" `
/Action:extract `
/SourceServerName:$ServerName `
/SourceDatabaseName:$DatabaseName `
/TargetFile:$script_path\DACPACs\$DatabaseName$now.dacpac `
/p:ExtractReferencedServerScopedElements=False `
/p:IgnorePermissions=False
}
Hope this helps.
Regards,
Alberto Morillo
SQLCoffee.com
Thanks to Abbas, the following code enable us to call a cmd process and pass command to it using PowerShell script.
$psi = New-Object System.Diagnostics.ProcessStartInfo;
$psi.FileName = "cmd.exe"; #process file
$psi.UseShellExecute = $false; #start the process from it's own executable file
$psi.RedirectStandardInput = $true; #enable the process to read from standard input
$p = [System.Diagnostics.Process]::Start($psi);
Start-Sleep -s 2 #wait 2 seconds so that the process can be up and running
$p.StandardInput.WriteLine("dir"); #StandardInput property of the Process is a .NET StreamWriter object
Now, How can I use a CMD process that already exists.
In better words, I want to use the PID of a cmd.exe process that is running and pass the command to it.
Based on #Falcon's comment:
I want to be sure that the CMD is running as SYSTEM
I think the code should work, which checks for a command shell running as SYSTEM. It will return true for each matching shell that's running as SYSTEM, with title=TEST:
Get-CimInstance Win32_Process -Filter "name = 'cmd.exe'" | ForEach-Object {
if ((Get-Process -Id $_.ProcessId).MainWindowTitle -eq 'TEST') {
(Invoke-CimMethod -InputObject $_ -MethodName GetOwner).User -eq 'SYSTEM'
}
}
The above code needs running in an elevated shell
The code based on this article checks for the command prompt being elevated:
$p = Get-Process -Name cmd | where {$_.MainWindowTitle -eq 'TEST'} |
Select Name, #{Name="Elevated"; Expression={ if ($this.Name -notin #('Idle','System')) {-not $this.Path -and -not $this.Handle} } }
The code above needs running in a non-elevated PowerShell instance. It is testing for the absence of a path & handle - which the non-elevated shell can't see for an elevated command prompt. Change the eq 'TEST' condition to match your window.
I need to call a batch file from powershell script. The batch file name will be decided using the parameters to PS file from user. I have this code but not working as expected. Could someone poing me my mistake? Everything seems fine but I am getting issues with the actual batch file calling (one of the last 4 statements)
param(
[string]$parts
)
$sharedDrive = "\\server\share"
$cred = get-credential "DOMAIN\"
$username = $cred.UserName
$password = $cred.GetNetworkCredential().Password
$net = New-Object -com WScript.Network
$net.mapnetworkdrive("", $sharedDrive, "true", $username, $password)
$BatchFilePath = $sharedDrive + "\Public\Upgrade\Application Folder"
IF ($parts -eq "P1") {
$selectedBatchFile = "`"" + $BatchFilePath + "\P1 Upgrade File.bat" + "`""
} ELSEIF ($parts -eq "P2") {
$selectedBatchFile = "`"" + $BatchFilePath + "\P1P2 Upgrade File.bat" + "`""
} ELSE {
Write-Host "Invalid Part specified. Choose one from: P1, P2"
}
$command1 = "/k $selectedBatchFile $username $password"
## I tried all the below but NONE worked
#& cmd "`"$command1`""
#& cmd "$command1"
#Start-Process "cmd.exe" -ArgumentList "$command1"
#Start-Process "cmd.exe" -ArgumentList "`"$command1`""
Try this
Invoke-Expression "cmd /k `"$selectedBatchFile`" $username $password"
NOTE: I do not normally suggest using Invoke-Expression if it executes code from text that a user has input. For instance, think about what happens if you use Read-Host to ask the user for their username and they type in ; Remove-Item C:\ -Recurse -Force -ErrorAction 0;. Yeah, that might be a bad day for you.
On V3/V4 you could also use --% but it requires storing your info in env vars which you might not want to do with a password:
$env:file = $selectedBatchFile
$env:un = $username
$env:pw = $password
cmd.exe /c --% "%file%" %un% %pw%
See this post for more details on --%.
Is there a reason you want to start it with cmd.exe /k?
start-process -filepath $selectedbatchfile -argumentlist $username,$password
I have a script that runs from a domain server and 'does work' on a domain server.
The work is divided up into jobs that are in scriptblocks that are called with invoke-command using a stored PSsession.
Results are logged on the domain server in a log file that includes a datetime stamp in the logfile name.
Now, I need to add another log that needs to reside on the remote on which the work is done. The log name format also needs to include a date and time stamp.
My problem is passing the name of the log to each of the jobs so that they write to the same file. I've played around with -ArgumentList, #args, and $args which I can get to run without errors but do nothing so I am not passing the logfile name correctly.
Below is a super simplified version of how I've structured my script.
Is it a mistake to nest the Start-Job in another script block? How would I pass my unique log file name to a number of these scriptblocks to capture success/failure and specific points?
#log file names, ps session and other variables declared here
$DoDomainWorkScriptBlock = {
Try {
start-job -name DoDomainWorkjob -scriptblock{
$command = "C:\Program Files\someprogram\someprogram.exe"
& $command -f someargs
If ($? -ne "True") {Throw 'Do work failed’}
" Do non-domain work job completed. "
}
} Catch {$Error[0] | Out-File $ErrorLog -Append}
}
#other jobs nested in other scriptblocks like the one above here
Invoke-Command -session $RemoteSession -scriptblock $DoDomainWorkScriptblock | Out-File $DomainProgressLog -Append
Invoke-Command -session $RemoteSession -command{Wait-Job -name DoDomainWorkjob } | Out-File $DomainProgressLog -Append
Invoke-Command -session $RemoteSession -command{Receive-Job -Name DoDomainWorkjob } | Out-File $DomainProgressLog –Append
#invoke start, wait, and receive job commands for the other jobs
You can pass arguments to script blocks like this:
$code = {
param( $foo )
Write-Host $foo
}
$bar = "bar"
Invoke-Command -ScriptBlock $code -ArgumentList $bar