i need to change node (true or false because of configuration)in xml file on a remote computer, working in Teamcity, wrote the following function
function Set-layout($hiddenfunctionality)
{
$properties = Resolve-Path ".\vsphere\properties.ps1"
. $properties
#Read env.properties
$configFilePath = Resolve-Path ".\environment\prod-env\env.properties"
Write-Host $configFilePath
$file = resolve-path("$configFilePath")
[xml]$doc = Get-Content $file
$node = $doc.SelectSingleNode("/project/property[#name='backend.server']")
$backend_ip = $node.value
$layoutRel = Resolve-Path ".\layout\layoutRel.ps1"
#Remote-Copy $layoutRel "\\$backend_ip\install"
Copy-Item $layoutRel "\\$backend_ip\install"
$dom_user = [string]($domain_name+ "\" + $domain_username)
$Connection = #{"server" = $backend_ip; "username" = $dom_user; "password" = $domain_password}
$rem_command = 'powershell -ExecutionPolicy RemoteSigned . c:\Empower\install\layoutRel.ps1 $hiddenfunctionality'
RemoteCommand $Connection $rem_command
}
this function is working and it call the script which will change the value of the node "configuration/appSettings/add[#key='opentext.empower.site.enableHiddenFunctionality"
Param ($hiddenfunctionality)
Write-Host "Updating C:\Program Files\Opentext\Empower\Web\Web.config"
[System.Xml.XmlDocument] $xd = new-object System.Xml.XmlDocument
$file = resolve-path("C:\Program Files\Opentext\Empower\Web\web\Web.config")
$xd.load($file)
$xd.SelectNodes("configuration/appSettings/add[#key='opentext.empower.site.enableHiddenFunctionality']").Item(0).SetAttribute( 'value', $hiddenfunctionality)
$xd.Save( $file)
Write-Host "Done"
In my teamcity configs do the following string
powershell . %teamcity.build.checkoutDir%\Build\CI_2.0\vsphere\env-handler.ps1; Set-layout $true
all it works, but field value in my file is empty, but should be true or false(
and i can't make a static true or false. it should be change because of some configurations in Teamcity
Maybe i can take the name of build configuration from teamcity anf if cat_1 than run "true" if cat_2 than "false" but i don't know how to do it
So , i've found that my script layoutrel.ps1 which will chamge node, don't take the parameter $hiddenfunctionality why it can be? When i gave for $hiddenfunctionality="true" it works(
Related
The following shortcut is created in SendTo and calls a PowerShell script. I want this script to be invisible (-WindowStyle Hidden) as the script uses Add-Type -AssemblyName System.Windows.Forms; $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property #{ InitialDirectory = $parent } and processes results based on the item selected in the OpenFileDialog.
$oShell = New-Object -ComObject Shell.Application
$lnk = $WScriptShell.CreateShortcut("$Env:AppData\Microsoft\Windows\SendTo\Get Info.lnk")
$lnk.TargetPath = "%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe"
$lnk.Arguments = "-WindowStyle Hidden -NoProfile -File `"C:\Scripts\Get Info.ps1`""
$lnk.Save()
However, the script is not silent, and throws up a blue PowerShell window briefly before the OpenFileDialog. How can I make the script completely silent when called by the shortcut?
Only way I know about to ensure this is using vbscript to launch your .ps1 script. It goes as follows:
Launcher.vbs
0 as argument in objShell.Run command,0 stands for Hide the window (and activate another window.)
Set objShell = CreateObject("WScript.Shell")
path = WScript.Arguments(0)
command = "powershell -NoProfile -WindowStyle Hidden -ExecutionPolicy ByPass -File """ & path & """"
objShell.Run command,0
myScript.ps1
Add-Type -AssemblyName System.Windows.Forms
$FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property #{
InitialDirectory = $parent
}
$FileBrowser.ShowDialog()
Now in your shortcut's Target field you can use use:
wscript path\to\launcher.vbs path\to\myScript.ps1
You can read more about this method in this site.
To expand upon Santiago's great answer, and with a real world example, my goal was to take an input from SendTo and then pass that input to PowerShell for additional processing. I don't need to see anything on the console so I wanted this to be hidden.
I want this for Beyond Compare, as I like the app a lot, but I really dislike how applications pollute our right-click context menu's with endless commands. I might only use Beyond Compare a couple of times per week, so I don't need it polluting my context menu for the 1,000+ other times per week that I right-click on something. I do this for all of my tools so that I have a very minimal and clean right-click context menu. The below would also apply to almost any other app that you would want a customised tooling in SendTo, and also almost unchanged for WinMerge if you prefer that tool (but Beyond Compare can also compare folders which can be very useful). For WinMerge, just break out of the script if a folder is selected at the first step as it cannot handle folders.
As I required two inputs, one from the initial SendTo, and the second from the OpenFileDialog or FolderBrowerDialog, this meant that I had to also pass the Argument given to the VBScript part of the solution. The syntax for that was a bit tricky to work out (it's 10+ years since I've had to use VBScript!), but is:
""" & path & """ """ & arg & """"
The solution then requires a .vbs launcher plus the .ps1 script and finally the shortcut in shell:sendto to call the scripts:
D:\MyPortableApps\ShortcutLauncher.vbs
Set oShell = CreateObject("WScript.Shell")
path = WScript.Arguments(0)
arg = WScript.Arguments(1)
PSCommand = "powershell -NoProfile -ExecutionPolicy ByPass -File """ & path & """ """ & arg & """"
oShell.run PScommand,0
D:\MyPortableApps\Compare with (Files or Folders, Beyond Compare).ps1
# Selected item in SendTo is the left side, then use OpenFileDialog or FolderBrowserDialog to pick the right side
$MyPrograms = "D:\MyPortableApps" # Location of my portable apps
$left_side = (Get-Item $args[0]).FullName # In case path contains '.' or '..'
$parent = Split-Path $left_side # Use this as InitialDirectory
$IsFolder = $false; if ((Get-Item $left_side) -is [System.IO.DirectoryInfo]) { $IsFolder = $true }
Add-Type -AssemblyName System.Windows.Forms # Required to access the OpenFileDialog object
if ($IsFolder) {
$FolderBrowser = New-Object System.Windows.Forms.FolderBrowserDialog # -Property #{ InitialDirectory = $parent }
$FolderBrowser.RootFolder = $parent
$FolderBrowser.Description = "Select Folder to compare to '$left_side':"
$Show = $FolderBrowser.ShowDialog()
if ($Show -eq "OK") {
$right_side = $FolderBrowser.SelectedPath
} else {
break
}
} else {
$FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property #{ InitialDirectory = $parent } # [Environment]::GetFolderPath('Desktop')
$FileBrowser.Title = "Select File to compare to '$left_side':"
$null = $FileBrowser.ShowDialog() # Assign to null as $FileBrowser does not return useful information by itself
$right_side = $FileBrowser.FileName
}
# $ButtonClicked = [System.Windows.Forms.MessageBox]::Show("Beyond Compare will be opened with the following panes:`n`nLeft side: '$left_side'`n`nRight side: '$right_side'", 'Open Beyond Compare?', 'OKCancel')
$appexe_pf = "C:\Program Files\Beyond Compare 4\BCompare.exe"
$appexe_sb = "$MyPrograms\Beyond Compare 4\BCompare.exe"
if ( (!(Test-Path $appexe_sb)) -and (!(Test-Path $appexe_pf))) { choco install beyondcompare -y }
if (Test-Path $appexe_pf) {
& $appexe_pf "$left_side" "$right_side"
} else {
& $appexe_sb "$left_side" "$right_side"
}
Snippet to create a shortcut in SendTo
function New-Shortcut ($mylnk, $mytgt, $myarg, $mywrk, $myico) {
$lnk = $WScriptShell.CreateShortcut($mylnk)
$lnk.TargetPath = $mytgt
if ($myarg -ne "") { $lnk.Arguments = $myarg }
if ($mywrk -ne "") { $lnk.WorkingDirectory = $mywrk }
if ($myico -ne "") { $lnk.IconLocation = $myico }
$lnk.Save()
}
$SendTo = "$Env:AppData\Microsoft\Windows\SendTo"
$lnkName = "Compare with (Files or Folders, Beyond Compare)"
$SendToLnk = "$SendTo\$lnkName.lnk"
$wscript = "C:\Windows\system32\wscript.exe"
New-Shortcut $SendToLnk $wscript "`"D:\MyPortableApps\ShortcutLauncher.vbs`" `"D:\MyPortableApps\$lnkName.ps1`"" "" ""
This question already has an answer here:
Issues with Target Path in powershell in creating a short cut
(1 answer)
Closed 3 years ago.
thanks for trying to help me^^
And sorry for my bad English(maybe?)
I'm trying to create a shortcut to a PowerShell-Script to execute it.
I'm using:
$WshShell = New-Object -comObject WScript.Shell
$link = $wshshell.CreateShortcut(”$home\Desktop\TimeStamp.lnk”)
$link.targetpath = ("%windir%\System32\WindowsPowerShell\v1.0\powershell.exe -noexit -File " + '"' + ($SaveDir + "\TimeStamp.ps1") + '"')
$link.save()
$SaveDir is the Path where the Script is.
It creates the shortcut, but then there is a error: (In German sorry) Der Wert liegt außerhalb des erwarteten Bereichs.
I tried to find a way to solve the problem. I now know whats the problem: It puts a " at the start and the end of the Target Location in the Properties of the Shortcut. Is there any way to prevent that?
To create a shortcut where you have arguments for the executable lik in your question, you will need to at least also use the Arguments property.
You can use this function which allows you to set all kinds of properties for a new shortcut, including the option to have the executable run as Administrator.
function New-Shortcut {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]$TargetPath, # the path to the executable
# the rest is all optional
[string]$ShortcutPath = (Join-Path -Path ([Environment]::GetFolderPath("Desktop")) -ChildPath 'New Shortcut.lnk'),
[string[]]$Arguments = $null, # a string or string array holding the optional arguments.
[string[]]$HotKey = $null, # a string like "CTRL+SHIFT+F" or an array like 'CTRL','SHIFT','F'
[string]$WorkingDirectory = $null,
[string]$Description = $null,
[string]$IconLocation = $null, # a string like "notepad.exe, 0"
[ValidateSet('Default','Maximized','Minimized')]
[string]$WindowStyle = 'Default',
[switch]$RunAsAdmin
)
switch ($WindowStyle) {
'Default' { $style = 1; break }
'Maximized' { $style = 3; break }
'Minimized' { $style = 7 }
}
$WshShell = New-Object -ComObject WScript.Shell
# create a new shortcut
$shortcut = $WshShell.CreateShortcut($ShortcutPath)
$shortcut.TargetPath = $TargetPath
$shortcut.WindowStyle = $style
if ($Arguments) { $shortcut.Arguments = $Arguments -join ' ' }
if ($HotKey) { $shortcut.Hotkey = ($HotKey -join '+').ToUpperInvariant() }
if ($IconLocation) { $shortcut.IconLocation = $IconLocation }
if ($Description) { $shortcut.Description = $Description }
if ($WorkingDirectory) { $shortcut.WorkingDirectory = $WorkingDirectory }
# save the link file
$shortcut.Save()
if ($RunAsAdmin) {
# read the shortcut file we have just created as [byte[]]
[byte[]]$bytes = [System.IO.File]::ReadAllBytes($ShortcutPath)
$bytes[21] = 0x22 # set byte no. 21 to ASCII value 34
[System.IO.File]::WriteAllBytes($ShortcutPath, $bytes)
}
# clean up the COM objects
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($shortcut) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($WshShell) | Out-Null
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
}
Using your example, use it like this:
$SaveDir = 'D:\' #'# the path to the .ps1 file
$props = #{
'ShortcutPath' = Join-Path -Path ([Environment]::GetFolderPath("Desktop")) -ChildPath 'TimeStamp.lnk'
'TargetPath' = '%windir%\System32\WindowsPowerShell\v1.0\powershell.exe'
'Arguments' = '-NoExit -NoLogo -File "{0}"' -f (Join-Path -Path $SaveDir -ChildPath 'TimeStamp.ps1')
# add more parameters here when needed
}
New-Shortcut #props
I have a script, below, which I have in a Scripts folder. It references a set of command prompt applications $cmd1.exe, etc.. Using either Powershell or the Integrated Powershell terminal in VS Code, I follow these steps to use it:
Dot source the script from the Scripts directory > .\new-customconfig.ps1,
Change to the working directory > cd [New Directory],
Use the function in the script and pass a filename from the working directory > New-CustomConfig .\FileName.
It passes the file from the working directory the first time I run the script, but from any subsequent runs, it looks for the file in the Scripts directory.
Is there something I am doing wrong?
Function New-CustomConfig {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[string]
$FileName
)
Begin {
#Set tools directory
$ToolD = '[Directory]\Tools'
#Clean up filename
$FileName = $FileName -replace '^[\W]*', ''
#Setup Executables
$cmdtools = "\cmd1.exe", "\cmd2.exe", "\cmd3.exe"
#Setup Arguments
$cmdargs = "cmd1args", "cmd2args", "cmd3args"
#Setup Write-Host Comments
$cmdecho = "echo1", "echo2", "echo3"
#Setup command object info
$cmdinfo = New-Object System.Diagnostics.ProcessStartInfo
$cmdinfo.RedirectStandardError = $true
$cmdinfo.RedirectStandardOutput = $true
$cmdinfo.UseShellExecute = $false
#Create command object
$cmd = New-Object System.Diagnostics.Process
"Generating Config for $FileName"
}
Process {
for ($i = 0; $i -le $cmdtools.Count; $i++) {
$cmdinfo.FileName = $ToolD + $cmdtools[$i]
$cmdinfo.Arguments = '' + $cmdargs[$i] + ''
Write-Host $i
Write-Host $cmdinfo.FileName
Write-Host $cmdinfo.Arguments
Write-Host $(Get-Location)
$cmdecho[$i]
$cmd.StartInfo = $cmdinfo
$cmd.Start() | Out-Null
$cmd.WaitForExit()
$stdout = $cmd.StandardOutput.ReadToEnd()
$stderr = $cmd.StandardError.ReadToEnd()
Write-Host "stdout: $stdout"
Write-Host "stderr: $stderr"
Write-Host "exit code: " + $p.ExitCode
}
}
End {
"Press any key to continue..."
$null = $host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
}
}
TL:DR actual question is at the bottom
I'm trying to troubleshoot a Powershell v1.0 script issue. The script basically downloads a file from an FTP site and puts it on a remote server via UNC and emails the success or failure of the task.
The script runs as a task with a generic ID that is a Domain Admin but is not used to log into systems so the server it runs off of does not contain a profile for it.
If I do a runas for that user and execute the script via command line it works flawlessly. However, if I try to run it as a task it runs then exits instantly. If I open a runas command prompt and run the scheduled task vi at he command line all I get back is:
SUCCESS: Attempted to run the scheduled task "Task Name".
I've tried writing variable values to a text file to see what is going on but it never writes even when I write them as the very first step of execution.
What I want to do is capture any script error messages you would normally see when trying to run the script and/or write the variable information to a text file.
Is there any way to do this? BTW I doing via calling powershell with the following arguments:
-file -ExecutionPolicy Bypass "d:\datscript\myscript.ps1"
-I've tried -command instead of -file.
-I've tried "d:\datscript\myscript.ps1 5>&1 test.txt"
-I've tried "d:\datscript\myscript.ps1 9>&1 test.txt"
-I've tried "d:\datscript\myscript.ps1 | out-file d:\datscript\test.txt"
Nothing worked. I'm sure I can fix whatever bug I have but I'm banging my head against the wall trying to get some kind of failure info.
--Update: Here is a copy of the script minus details--
#-------------------------------------------------------------------------------------------------------------------------------------------------------------
#
#Variable Declaration
#
#$path = Path on local server to downlaod DAT to
#$olddat = Old/last DAT downloaded
#$currentdat = Next DAT number
#$ftpsite = McAfee FTP site. Update if path changes
#$ftpuser = FTP user (anon login)
#$ftppass = FTP password (anon login)
#$tempstring = Manipulation variable
#$gotdat = Boolean if updated DAT exists
#$success = Status if a new DAT exists and has been downloaded (used for email notification).
#$thetime = Variable use dto hold time of day manipulation.
$path = "\\myservername\ftproot\pub\mcafee\datfiles\"
$olddat = ""
$currentdat =""
$ftpsite = "ftp://ftp.nai.com/virusdefs/4.x/"
$ftpuser = "something"
$ftppass = "anything"
$tempstring =""
$gotdat = "False"
$success = ""
$thetime = ""
#
#Normalized functions handles UNC paths
#
function Get-NormalizedFileSystemPath
{
<#
.Synopsis
Normalizes file system paths.
.DESCRIPTION
Normalizes file system paths. This is similar to what the Resolve-Path cmdlet does, except Get-NormalizedFileSystemPath also properly handles UNC paths and converts 8.3 short names to long paths.
.PARAMETER Path
The path or paths to be normalized.
.PARAMETER IncludeProviderPrefix
If this switch is passed, normalized paths will be prefixed with 'FileSystem::'. This allows them to be reliably passed to cmdlets such as Get-Content, Get-Item, etc, regardless of Powershell's current location.
.EXAMPLE
Get-NormalizedFileSystemPath -Path '\\server\share\.\SomeFolder\..\SomeOtherFolder\File.txt'
Returns '\\server\share\SomeOtherFolder\File.txt'
.EXAMPLE
'\\server\c$\.\SomeFolder\..\PROGRA~1' | Get-NormalizedFileSystemPath -IncludeProviderPrefix
Assuming you can access the c$ share on \\server, and PROGRA~1 is the short name for "Program Files" (which is common), returns:
'FileSystem::\\server\c$\Program Files'
.INPUTS
String
.OUTPUTS
String
.NOTES
Paths passed to this command cannot contain wildcards; these will be treated as invalid characters by the .NET Framework classes which do the work of validating and normalizing the path.
.LINK
Resolve-Path
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[Alias('PSPath', 'FullName')]
[string[]]
$Path,
[switch]
$IncludeProviderPrefix
)
process
{
foreach ($_path in $Path)
{
$_resolved = $_path
if ($_resolved -match '^([^:]+)::')
{
$providerName = $matches[1]
if ($providerName -ne 'FileSystem')
{
Write-Error "Only FileSystem paths may be passed to Get-NormalizedFileSystemPath. Value '$_path' is for provider '$providerName'."
continue
}
$_resolved = $_resolved.Substring($matches[0].Length)
}
if (-not [System.IO.Path]::IsPathRooted($_resolved))
{
$_resolved = Join-Path -Path $PSCmdlet.SessionState.Path.CurrentFileSystemLocation -ChildPath $_resolved
}
try
{
$dirInfo = New-Object System.IO.DirectoryInfo($_resolved)
}
catch
{
$exception = $_.Exception
while ($null -ne $exception.InnerException)
{
$exception = $exception.InnerException
}
Write-Error "Value '$_path' could not be parsed as a FileSystem path: $($exception.Message)"
continue
}
$_resolved = $dirInfo.FullName
if ($IncludeProviderPrefix)
{
$_resolved = "FileSystem::$_resolved"
}
Write-Output $_resolved
}
} # process
} # function Get-NormalizedFileSystemPath
#
#Get the number of the exisiting DAT file and increment for next DAT if the DAT's age is older than today.
# Otherwise, exit the program if DATs age is today.
#
$tempstring = "xdat.exe"
$env:Path = $env:Path + ";d:\datscript"
$path2 ="d:\datscript\debug.txt"
add-content $path2 $path
add-content $path2 $olddat
add-content $path2 $currentdat
add-content $path2 $success
add-content $path2 " "
$path = Get-NormalizedFileSystemPath -Path $path
Set-Location -Path $path
$olddat = dir $path | %{$_.Name.substring(0, 4) }
$olddatfull = "$olddat" + "$tempstring"
if ( ((get-date) - (ls $olddatfull).LastWriteTime).day -lt 1)
{
#***** Commented out for testing!
# exit
}
$currentdat = [INT] $olddat
$currentdat++
$currentdat = "$currentdat" + "$tempstring"
add-content $path2 $olddat
add-content $path2 $currentdat
add-content $path2 $success
add-content $path2 " "
#
#Connect to FTP site and get a current directory listing.
#
[System.Net.FtpWebRequest]$ftp = [System.Net.WebRequest]::Create($ftpsite)
$ftp.Method = [System.Net.WebRequestMethods+FTP]::ListDirectoryDetails
$response = $ftp.getresponse()
$stream = $response.getresponsestream()
$buffer = new-object System.Byte[] 1024
$encoding = new-object System.Text.AsciiEncoding
$outputBuffer = ""
$foundMore = $false
#
# Read all the data available from the ftp directory stream, writing it to the
# output buffer when done. After that the buffer is searched to see if it cotains the expected
# lastest DAT.
#
do
{
## Allow data to buffer for a bit
start-sleep -m 1000
## Read what data is available
$foundmore = $false
$stream.ReadTimeout = 1000
do
{
try
{
$read = $stream.Read($buffer, 0, 1024)
if($read -gt 0)
{
$foundmore = $true
$outputBuffer += ($encoding.GetString($buffer, 0, $read))
}
} catch { $foundMore = $false; $read = 0 }
} while($read -gt 0)
} while($foundmore)
$gotdat = $outputbuffer.Contains($currentdat)
$target = $path + $currentdat
#
# Downloads DATs and cleans up old DAT file. Returns status of the operation.
# Return 1 = success
# Return 2 = Latest DAT not found and 4pm or later
# Return 3 = DAT available but did not download or is 0 bytes
# Return 4 = LatesT DAT not found and before 4pm
#
$success = 0
if ($gotdat -eq "True")
{
$ftpfile = $ftpsite + $ftppath + $currentdat
write-host $ftpfile
write-host $target
$ftpclient = New-Object system.Net.WebClient
$uri = New-Object System.Uri($ftpfile)
$ftpclient.DownloadFile($uri, $target)
Start-Sleep -s 30
if ( ((get-date) - (ls $target).LastWriteTime).days -ge 1)
{
$success = 3
}
else
{
$testlength = (get-item $target).length
if( (get-item $target).length -gt 0)
{
Remove-Item "$olddatfull"
$success = 1
}
else
{
$success = 3
}
}
}
else
{
$thetime = Get-Date
$thetime = $thetime.Hour
if ($thetime -ge 16)
{
$success = 2
}
else
{
$success = 4
exit
}
}
#
# If successful download (success = 1) run push bat
#
if ($success -eq 1)
{
Start-Process "cmd.exe" "/c c:\scripts\mcafeepush.bat"
}
#Email structure
#
#Sends result email based on previous determination
#
#SMTP server name
$smtpServer = "emailserver.domain.com"
#Creating a Mail object
$msg = new-object Net.Mail.MailMessage
#Creating SMTP server object
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = "email1#domain.com"
$msg.ReplyTo = "email2#domain.com"
$msg.To.Add("email2#domain.com")
switch ($success)
{
1 {
$msg.subject = "McAfee Dats $currentdat successful"
$msg.body = ("DAT download completed successfully. Automaton v1.0")
}
2 {
$msg.subject = "McAfee DATs Error"
$msg.body = ("Looking for DAT $currentdat on the FTP site but I coud not find it. Human intervention may be required. Automaton v1.0")
}
3 {
$msg.subject = "McAfee DATs Error"
$msg.body = ("$currentdat is available for download but download has failed. Human intervention will be required. Automaton v1.0")
}
default {
$msg.subject = "DAT Automaton Error"
$msg.body = ("Something broke with the McAfee automation script. Human intervention will be required. Automaton v1.0")
}
}
#Sending email
$smtp.Send($msg)
#Needed to keep the program from exiting too fast.
Start-Sleep -s 30
#debugging stuff
add-content $path2 $olddat
add-content $path2 $currentdat
add-content $path2 $success
add-content $path2 " "
Apparently you have an error in starting Powershell, either because execution policy is different on the Powershell version you start, or on the account, or there is an access error on the scheduled task. To gather actual error, you can launch a task like so:
cmd /c "powershell.exe -file d:\datscript\myscript.ps1 test.txt 2>&1" >c:\windows\temp\test.log 2&>1
This way if there would be an error on starting Powershell, it will be logged in the c:\windows\temp\test.log file. If the issue is in execution policy, you can create and run (once) a task with the following:
powershell -command "Get-ExecutionPolicy -List | out-file c:/windows/temp/policy.txt; Set-ExecutionPolicy RemoteSigned -Scope LocalMachine -Force"
Running a task under the account you plan to run your main task will first get the policies in effect (so that if setting machine-level policy won't help, you'll know what scope to alter) and set machine-level policy to "RemoteSigned", the least restrictive level beyond allowing every script (highly not recommended, there are encoder scripts written on Powershell that can ruin your data).
Hope this helps.
UPDATE: If that's not policy, there might be some errors in properly writing the parameters for the task. You can do this: Create a .bat file with the string that launches your script and redirects output to say test1.txt, then change the scheduled task to cmd.exe -c launcher.bat >test2.txt, properly specifying the home folder. Run the task and review both files, at least one of them should contain an error that prevents your script from launching.
I want to run a PS script when I want to publish to FTP server. I took this script as structure : structure script.
I have very simple folder :
C:\Uploadftp\Files\doc.txt
C:\Uploadftp\Files\Files2
C:\Uploadftp\Files\Files2\doc2.txt
nothing fancy there.
Here is my script :
cd C:\Uploadftp
$location = Get-Location
"We are here: $location"
$user = "test" # Change
$pass = "test" # Change
## Get files
$files = Get-ChildItem -recurse
## Get ftp object
$ftp_client = New-Object System.Net.WebClient
$ftp_client.Credentials = New-Object System.Net.NetworkCredential($user,$pass)
$ftp_address = "ftp://test/TestFolder"
## Make uploads
foreach($file in $files)
{
$directory = "";
$source = $($file.DirectoryName + "/" + $file);
if ($file.DirectoryName.Length -gt 0)
{
$directory = $file.DirectoryName.Replace($location,"")
}
$directory = $directory.Replace("\","/")
$source = $source.Replace("\","/")
$directory += "/";
$ftp_command = $($ftp_address + $directory + $file)
# Write-Host $source
$uri = New-Object System.Uri($ftp_command)
"Command is " + $uri + " file is $source"
$ftp_client.UploadFile($uri, $source)
}
I keep getting this error :
Exception calling "UploadFile" with "2" argument(s): "An exception occurred during a WebClient request."
If I hardcode specific folder for $uri and tell source to be some specific folder on my computer, this script doesn't create directory, it creates a file. What am I doing wrong?
P.S. dont hit me too hard, its my fist time ever doing something in power shell.
Try the "Create-FtpDirectory" function from https://github.com/stej/PoshSupport/blob/master/Ftp.psm1
function Create-FtpDirectory {
param(
[Parameter(Mandatory=$true)]
[string]
$sourceuri,
[Parameter(Mandatory=$true)]
[string]
$username,
[Parameter(Mandatory=$true)]
[string]
$password
)
if ($sourceUri -match '\\$|\\\w+$') { throw 'sourceuri should end with a file name' }
$ftprequest = [System.Net.FtpWebRequest]::Create($sourceuri);
$ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::MakeDirectory
$ftprequest.UseBinary = $true
$ftprequest.Credentials = New-Object System.Net.NetworkCredential($username,$password)
$response = $ftprequest.GetResponse();
Write-Host Upload File Complete, status $response.StatusDescription
$response.Close();
}