I'm using the following powershell script to monitor new files coming
in an IBM iSeries shared folder.
# variables
#$folder = "\\10.10.0.120\transform\BE\FORM"
#$folder = "C:\Users\Administrator.ALI\Desktop\AS400"
#$folder = "\\nb091002\Temp"
$folder = "I:\"
$filter = "*.txt"
$aswform = "C:\ASWFORM\aswform.exe"
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = $folder
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $false
$watcher.NotifyFilter = [System.IO.NotifyFilters]::LastWrite -bor [System.IO.NotifyFilters]::FileName
while($TRUE){
$result = $watcher.WaitForChanged([System.IO.WatcherChangeTypes]::Changed -bor [System.IO.WatcherChangeTypes]::Renamed -bOr [System.IO.WatcherChangeTypes]::Created, 2000);
if($result.TimedOut){
continue;
}
Write-Host $result.Name
#$aswform $folder
}
This seems to work fine on local folders or domain shares.
I've tried mapping the iSeries shared folder to a network drive but it doesn't work.
(10.10.0.120 is the AS400)
I'm pretty sure it has to do something with credentials....
Strange thing is I can access the shared folder from within Windows perfectly.
Does anybody have any clues or tips for me?
PS: little detail, I'll be running this script through task sheduler with this trigger
powershell -NoExit -WindowStyle Hidden -File "C:\ASWFORM\watcher.ps1"
But first I need it working when running the script manually!
I have not been able to get FileSystemWatcher to work unless the target directory was a Windows NTFS drive. If I specify the drive letter of the mapped directory I get
Exception setting "Path": "The directory name W:\ is invalid."
If I use the UNC I get
Exception calling "WaitForChanged" with "2" argument(s): "Error reading the \\\\path.to.my.ibm.i\\root\ directory."
Against a Novell file server I get the directory name is invalid if I use a drive letter. If I use a UNC against a Novell drive it does run, but doesn't detect any changes to the file system. Works fine against a local drive and also against a Windows file server on my network.
I solved the problem by writing a small C# console application to poll the folder
instead of using the .Net FileSystemWatcher object.
I manually (instsrv.exe) installed this program as a service and it seems to be running ok.
If you want the code, please send me a PM and I'll see to it that you get it.
Related
Getting ready to use a few scripts that I have had written for a while but was never able to solve one particular issue. Hoping to find a solution.
The project is to do a Win10 Build upgrade to around 900 machines in one weekend. Need to ensure they are back up in time and that the upgrade was successful.
Files are staged on a file share. Scripts are stored on the same share. A task is going to created with a bat file on each machine to go get the scripts and execute them.
In the scripts I have it set to record data and its progress to its own file on the network with the name of the file being computer.txt
The Issue:
After the upgrade finishes rebooting it will execute a task that is set to run 'AtStartup'. I have it reconnect to the network share immediately to start logging its status again. It will sometimes work perfectly fine and other times it will not. 50/50. The script works aside from this. Everything finishes fine.
Why the logging?
There are a lot of computers to watch all at one time with a limited number of people to watch over them and address issues. The logs will let me know where there might be a possible issue with how I have it logging. I would like to continue to get the data post reboots.
It doesn't appear to be a network issue because I have verified the machine is communicating.
Ive tried adding a sleep timer to give Windows 2 minutes to finish booting. That didn't help.
I am not sure where to look to find why it works only sometimes.
Mapping of Network Share Path and setting file variable
$Drive_Root_Path = "\\File Path\"
$Drive_Letter = "X"
Remove-PSDrive $Drive_Letter
$Drive = New-PSDrive -Name $Drive_Letter -PSProvider FileSystem -Root $Drive_Root_Path
$Win10_Upgrade_Log_Folder = $Drive.Root + "Log Folder\"
$Log_File = $Win10_Upgrade_Log_Folder + $env:COMPUTERNAME + ".txt"
Example how data is added to the file
Add-Content -Path $Log_File -Value (Get-Date) -NoNewline
Add-Content -Path $Log_File -Value " Setting Executino Policy back to Restricted."
I know there are better solutions to upgrade Windows but with the options available to me, I had to come up with something. It works minus the part of logging after reboot.
I agree with #Theo to try using a UNC path instead of a mapped drive. I also advocate to try also using fully qualified domain names in the path. This makes your code even simpler:
$Win10_Upgrade_Log_Folder = "\\server.contoso.com\Log Folder\"
$Log_File = $Win10_Upgrade_Log_Folder + $env:COMPUTERNAME + ".txt"
And adding content is the same:
Add-Content -Path $Log_File -Value (Get-Date) -NoNewline
Add-Content -Path $Log_File -Value " Setting Executino Policy back to Restricted."
Lest say there is a network folder \\my_server\my_root\my_dir.
To access this folder these credentials required username: my_doman\my_user password: my_password.
Now in my program first it try to map network folder to a local drive. If there is a exception, it consider as folder not exist. I think this is not a good way.
Is there a way to check this folder exist without try to map to a local drive? I'm looking for something like
[System.IO.Path]::Exist("\\my_server\my_root\my_dir","my_doman\my_user","my_password")
I'm using Powershell 5
This is how I map the drive now
try{
$net = new-object -ComObject WScript.Network
$net.MapNetworkDrive($free_drive, $network_dir, $false, "domain\user", "password")
}catch{
Write-host: "folder does not exist"
}
Using New-PSDrive:
New-PSDrive -Name Q -PSProvider FileSystem -Root \\my_server\my_root\my_dir -Credential my_domain\my_user -Persist
Old School method using cmdline utility:
net use \\my_server\my_root\my_dir /user:my_domain\my_user my_password
start \\my_server\my_root\my_dir
For mapping you can use this:
$net = New-Object -comobject Wscript.Network
$net.MapNetworkDrive("Q:","\\my_server\my_root\my_dir",0,"my_domain\my_user","my_password")
For testing the path, you can use:
Test-Path \\my_server\my_root\my_dir
Note:You will get a boolean value in return from the test path.
Hope it helps.
Assuming that on the machine executing the script you're able to log in as the user under which you want to connect to the remote share, you could use Invoke-Command to invoke Test-Path as another user:
$pathExists = Invoke-Command -ComputerName . -Credential $credentials -ScriptBlock {
Test-Path -Path "\\my_server\my_root\my_dir"
}
if ($pathExists)
{
# my_dir\ exists
}
else
{
# my_dir\ is inaccessible/non-existent
}
I'm not in a position to test this at present but I suspect you may need to include -Authentication Credssp as a parameter to Invoke-Command (assuming the necessary environment for that is in place) due to the double-hop problem.
Of course, if you're checking for the existence of that directory under another user in order to make decisions for future filesystem operations to be executed as that same user, you would then need to Invoke-Command another batch of operations or include them after Test-Path. At that point you might be better off connecting to the share under alternate credentials in the usual way. It's just the difference between executing as another user and connecting as another user, each with their own pros and cons.
I was having the same problem checking the folder and/or file existence on a remote server before copying the file from deployment server. Nothing worked for me and ended up in a huge frustration.
I then tried this...
$pathExists = Invoke-Command -ComputerName <remoteServerName> -Credential $credentials
-ScriptBlock {
Test-Path -Path <AbsolutePath> "UNC path does not work here and you must use Absolute
path. eg. instead of \\Server use D:\Dir1 or D:\Dir1\File1.bat"
}
if (-not ($pathExists))
{
write-host "Directory or File does not exist"
}
else
{
write-host "Directory or File exist"
}
This worked just fine for me after using the absolute path in the Test-Path. For some reason the UNC path does not work! Hope, this helps someone!
I have a simple PowerShell script that copies a file from a mapped network drive, if it's modified in past 1 day.
$source = "Z:\\"
$target = "E:\target"
$files = get-childitem $source
foreach ($file in $files) {
if($file.LastWriteTime -ge (get-date).AddDays(-1)) {
Copy-Item $file.FullName $target
}
}
This script runs fine if I manually execute it.
If I try to use a scheduled task, the copy does not run. I confirmed the script is running by having it make a directory.
If I instead copy from a local drive instead of a network drive, the script runs fine with a scheduled task.
Schedule Task is running as an Admin Account.
Script copying file from network drive runs fine manually but not via scheduled task. Script runs fine as task if copying from local but not network drive.
Any ideas?
Try specifying the full UNC path rather than a network drive. (Network drives are a per-user configuration item.)
Map the drive as a temporary PowerShell drive...add the following as the first line of the script
New-PSDrive -Name Z -PSProvider FileSystem -Root \\server\sharename
I have the following piece of PowerShell code:
$files = Get-ChildItem E:\Local_Files\Performance\*.txt -Recurse
foreach ($file in $files) {
(Get-Content $file.PSPath) |
Where-Object { $_.Trim() -ne "" } |
Set-Content $file.PSPath
}
Move-Item -Path E:\Local_Files\Performance\*.* -Destination E:\Local_Files\ -Force
It deletes empty rows for all files in a folder. Then, it moves any file on that folder to a second one. Z:\ is a mapped network drive for a network folder. If I run the script in PowerShell, it works. When I schedule it in the Task Scheduler, it only works the first bit (the Trim() method).
I have setup the same username to run the job in both cases. If I use a local folder as a target for move-item, it works in the Task Scheduler as well.
Do you have any idea why it might not be working?
I am on Windows Server 2012 R2.
Many thanks,
Mapped drives are only mapped when a user logs on interactively. For a scheduled task, there is no interactive logon and therefore no mapped drives, so any attempt to use them will fail.
You can either:
Map the drive letter in your script with New-PSDrive
Use the UNC path to the share (preferred method).
Also bear in mind that the user account under which your task executes must have appropriate permissions on that UNC path/share.
I'm currently trying to pull msinfo data from a remote server and then save that output onto a share located on another server. When I run the command, a progress bar appears and then completes without apparent issue, but the file isn't saved to the UNC path. I've verified that I have permissions on the share and that the nfo generation itself works. Any ideas?
C:\Windows\system32>msinfo32 /computer servername /nfo \\sharename\filename.nfo
Very Strange, It works on CMD but not with Powershell, Not had the time to explore it, However If you need to run it in powershell you can take this workaround:
$TempFile = [System.IO.Path]::GetTempFileName()
C:\Windows\system32\msinfo32 /computer Computer /nfo $TempFile
Do
{
Sleep 5
}
Until (!(Get-Process msinfo32 -ErrorAction SilentlyContinue))
Copy-Item $TempFile \\Computer\Share\output.nfo
$TempFile | Remove-Item -Force
Got it figured out - I was able to use the switch user param to save the file after pulling it from the server.
Thanks!