How can I save an XML in a path with 260+ characters? - powershell

Here is my situation. I have an XML that resides in a path that contains 260+ characters. One of the folders in this path will always be random, another one is based on versions so it could be different as well.
I am trying to load the XML, make changes to it, and save it back. So far I haven't been able to do that in place so I am copying it to C:\Windows\Temp, making the changes there, and then trying to copy it back in place, which has worked in manual tests.
My main problem is the file path contains more than 260+ characters so Copy-Item hasn't worked properly and I haven't been able to figure out how to get Robocopy to work since I have to use a variable for the path because of the random folders.
XML modification works, copying out to Temp works, the problem I am having is copying it back to the 260+ character path.
I am very new to Powershell as an FYI. Here is what I have come up with so far:
$folderLocation = Get-ChildItem -Path C:\Windows\System32\config\systemprofile\AppData\Local\ProgramA\ -Filter userConfig.xml -Recurse |
Sort-Object LastWriteTime |
Select-Object -last 1 |
Select-Object Directory |
Format-Table -hide
foreach ($f in $folderLocation){
Copy-Item userConfig.xml C:\Windows\Temp
}
$myXML = New-Object System.Xml.XmlDocument
$myXML.Load("C:\Windows\Temp\userConfig.xml")
$isActive = $myXML.SelectSingleNode("//setting[#name = 'Active']")
$isActive.value = "True"
$myXML.Save("C:\Windows\Temp\userConfig.xml")
$convertFolder = [System.String]$folderLocation
Copy-Item ("C:\Windows\Temp\userConfig.xml") $convertFolder
Here is the Robocopy code I tried, I know it's a hackjob but I tried to imitate some things I saw online:
function copy-stuff
{
param([string]$source = "C:\Windows\Temp",
[string]$destination = $convertFolder,
[string]$options = “/R:0″,”/W:0″,”/COPY:DAT”)
[string]$file = "userConfig.xml"
robocopy $source $destination $file $options
}
I tried a couple different things with robocopy but this is what I still had saved. I haven't studied up on creating and using functions in Powershell so this was a monkey see monkey do attempt.

Addressing the Robocopy part of your code:
It looks like you aren't passing anything to your function, but are relying on default values. Try this:
function Copy-Stuff {
param (
[string]$source,
[string]$destination,
[string]$file
)
robocopy $source $destination $file /R:0 /W:0 /COPY:DAT
}
$convertFolder = "blahblah"
Copy-Stuff -Source "C:\Windows\Temp" -Destination $convertFolder -File "userConfig.xml"
If the options never change, then don't bother making them a variable.

Related

Powershell script: get multiple properties from "Get-Childitem" in a loop

i am absolutely not a programmer, so please excuse my ignorance and clumsy code.
My task is to change one value per file with 1.25*value in a number of xml-files in a folder.
I have come up with the following code which seems to go through all files and changes each value correctly, then writes the new changed files to a new subfolder "DD1". My test code so far only wrote to a single file test.xml all the time, overwriting it per each loop.
I want the altered files to be named exactly like the original ones, so i am trying to grab each filename within the loop but so far to no avail. Maybe you can tell me, what to put instead of the "????????"
New-Item '.\DD1' -ItemType Directory
Get-ChildItem -Path .\ -Filter *.pws |
Foreach-Object {
[xml]$myXML = Get-Content $_.FullName
$valueString = $myXML.settings.TuningMenu.FF
$valueInt = [int]$valueString
$newValueInt = $valueInt*1.25
$newValueString = [string]$newValueInt
$myXML.settings.TuningMenu.FF = $newValueString
[string]$path = $PWD
[string]$file = ????????
$fullName = $path+"\DD1\"+$file
$myXML.Save("$fullName")
}

Powershell: ForEach Copy-Item doesn't rename properly when retrieving data from array

I am pretty new to PowerShell and I need some help. I have a .bat file that I want to copy as many times as there are usernames in my array and then also rename at the same time. This is because the code in the .bat file remains the same, but for it to work on the client PC it has to have the username as a prefix in the filename.
This is the code that I have tried:
$usernames = Import-Csv C:\Users\Admin\Desktop\usernames.csv
$file = Get-ChildItem -Path 'C:\Users\Admin\Desktop\generatedbat\' -Recurse
foreach ($username in $usernames)
{
ForEach-Object {Copy-Item $file.FullName ('C:\Users\Admin\Desktop\generatedbat\' + $username + $File.BaseName + ".bat")}
}
This copies everything and it kind of works but I have one problem.
Instead of having this filename: JohnR-VPNNEW_up.bat
I get this: #{Username=JohnR}-VPNNEW_up.bat
Any help? Thanks!
So you have one .bat file C:\Users\Admin\Desktop\generatedbat\VPNNEW_up.bat you want to copy to the same directory with new names taken from the usernames.csv --> Username column.
Then try
# get an array of just the UserNames column in the csv file
$usernames = (Import-Csv -Path 'C:\Users\Admin\Desktop\usernames.csv').Username
# get the file as object so you can use its properties
$originalFile = Get-Item -Path 'C:\Users\Admin\Desktop\generatedbat\VPNNEW_up.bat'
foreach ($username in $usernames) {
$targetFile = Join-Path -Path $originalFile.DirectoryName -ChildPath ('{0}-{1}' -f $username, $originalFile.Name)
$originalFile | Copy-Item -Destination $targetFile -WhatIf
}
I have added switch -WhatIf so you can first test this out. If what is displayed in the console window looks OK, then remove that -WhatIf safety switch and run the code again so the file is actually copied
I kept the code the same but instead of using a .csv file I just used a .txt file and it worked perfectly.

Moving, Encrypting and storing .txt and .pc files to .pgp in PowerShell

I have been learning how to use PowerShell to do some automation that will convert files to a .pgp format. These files end in .txt or .qc. These files are created on one of the servers in the environment, then converted manually, then transferred to another server in the same environment.
I have developed a script that will perform this task, however it will only do one file (I would like for to do all of the files). I the script will not strip the native extension and replace it with only a .pgp extension.
I have included the script below.
PowerShell Script
$_SourcePath = (\\Server1\Location1\*.txt",\\Server1\Location1\*.qc")
$_DestinationPath = "\\Server1\Location2\"
$_SourcePath2 = "\\Server1\Location2\"
$_DestinationPath2 = "\\Server2\Location1\"
Move-item –path $_SourcePath –destination $_DestinationPath
ConvertTo-PgpEncryptedFile -Path "\\Server1\Location2\*.*" -key "\\server3\location1\Enycrption key.asc"
Move-item –path $_SourcePath2 –destination $_DestinationPath2
Again, with this script I can move all the files I need, but it will only encrypt one file and move it to the correct location. I would like for it to encrypt all the files and remove the .txt or .qc extension and replace it with .pgp.
Any Help would be appreciated….
You probably want something along this line:
$SourcePath = '\\Server1\Location1\'
$DestinationPath = '\\Server1\Location2\'
$DestinationPath2 = '\\Server2\Location1\'
$GCIArgs = #{Path = "$($SourcePath)*"
Include = "*.txt","*.qc"
}
$SrcFiles = Get-ChildItem #GCIArgs
ForEach ($File in $SrcFiles) {
Move-item –path "$File.FullName" –destination "$DestinationPath"
$CTPGPArgs =
#{Path = $(Join-Path "$DestinationPath" "$File.Name")
Key = '\\server3\location1\Enycrption key.asc'
}
ConvertTo-PgpEncryptedFile #CTPGPArgs
$EncName = $($_.Name -split('.'))[0] + '.pgp'
$MIArgs = #{Path = "$($CTPGPArgs.Path)"
Destination = $(Join-Path "$DestinationPath2" "$EncName")
}
Move-item #MIArgs
}
I've used single quotes in strings where interpretation is not needed. I've also used splatting to shorten lines and make reading easier.
I eliminated the _ in regular variable names so not to confuse them with items from a pipeline.
Used final Move-Item to also change file extension to .pgp.
Note: I tested as much of this as I could piece-meal but not having servers or the cmdlet ConvertTo-PgpEncryptedFile I couldn't test the entire program.

Compress File per file, same name

I hope you are all safe in this time of COVID-19.
I'm trying to generate a script that goes to the directory and compresses each file to .zip with the same name as the file, for example:
sample.txt -> sample.zip
sample2.txt -> sample2.zip
but I'm having difficulties, I'm not that used to powershell, I'm learning and improving this script. In the end it will be a script that deletes files older than X days, compresses files and makes them upload in ftp .. the part of excluding with more than X I've already managed it for days, now I grabbed a little bit on this one.
Last try at moment.
param
(
#Future accept input
[string] $InputFolder,
[string] $OutputFolder
)
#test folder
$InputFolder= "C:\Temp\teste"
$OutputFolder="C:\Temp\teste"
$Name2 = Get-ChildItem $InputFolder -Filter '*.csv'| select Name
Set-Variable SET_SIZE -option Constant -value 1
$i = 0
$zipSet = 0
Get-ChildItem $InputFolder | ForEach-Object {
$zipSetName = ($Name2[1]) + ".zip "
Compress-Archive -Path $_.FullName -DestinationPath "$OutputFolder\$zipSetName"
$i++;
$Name2++
if ($i -eq $SET_SIZE) {
$i = 0;
$zipSet++;
}
}
You can simplify things a bit, and it looks like most of the issues are because in your script example $Name2 will contain a different set of items than the Get-ChildItem $InputFolder will return in the loop (i.e. may have other objects other than .csv files).
The best way to deal with things is to use variables with the full file object (i.e. you don't need to use |select name). So I get all the CSV file objects right away and store in the variable $CsvFiles.
We can additionally use the special variable $_ inside the ForEach-Object which represents the current object. We also can use $_.BaseName to give us the name without the extension (assuming that's what you want, otherwise use $_Name to get a zip with the name like xyz.csv).
So a simplified version of the code can be:
$InputFolder= "C:\Temp\teste"
$OutputFolder="C:\Temp\teste"
#Get files to process
$CsvFiles = Get-ChildItem $InputFolder -Filter '*.csv'
#loop through all files to zip
$CsvFiles | ForEach-Object {
$zipSetName = $_.BaseName + ".zip"
Compress-Archive -Path $_.FullName -DestinationPath "$OutputFolder\$zipSetName"
}

How to use an array in a zip function using powershell?

I am still pretty new to scripting and "programming" at all. if you miss any information here let me know.
This is my working zip function:
$folder = "C:\zipthis\"
$destinationFilePath = "C:\_archive\zipped"
function create-7zip{
param([string] $folder,
[String] $destinationFilePath)
write-host $folder $destinationFilePath
[string]$pathToZipExe = "C:\Program Files (x86)\7-Zip\7zG.exe";
[Array]$arguments = "a", "-tzip", "$destinationFilePath", "$folder";
& $pathToZipExe $arguments;
}
Get-ChildItem $folder | ? { $_.PSIsContainer} | % {
write-host $_.BaseName $_.Name;
$dest= [System.String]::Concat($destPath,$_.Name,".zip");
(create-7zip $_.FullName $dest)
}
create-7zip $folder $destinationFilePath
now I want him to zip special folders which I already sorted out :
get-childitem "C:\zipme\" | where-Object {$_.name -eq "www" -or $_.name -eq "sql" -or $_.name -eq "services"}
This small function finds the 3 folders I need called www, sql and services. But I didn't manage to insert this into my zip function, so that exactly this folders are zipped and put into C:\_archive\zipped
Because a string is used instead of an array, he tried always to look for a folder called wwwsqlservice which is not there. I tried to put an array using #(www,sql,services) but i had no success, so whats the right way, if there is one?
It should compatible with powershell 2.0, no ps3.0 cmdlets or functions please.
thanks in advance!
Here's a really simple example of what you want to do, removed from the context of your function. It assumes that your destination folders already exist (You can just use Test-Path and New-Item to create them if they don't), and that you're using 7z.exe.
$directories = #("www","sql","services")
$archiveType = "-tzip"
foreach($dir in $directories)
{
# Use $dir to update the destination each loop to prevent overwrites!
$sourceFilePath = "mySourcePath\$dir"
$destinationFilePath = "myTargetPath\$dir"
cmd /c "$pathToZipExe a $archiveType $destinationFilePath $sourceFilePath"
}
Overall it looks like you got pretty close to a solution, with some minor changes needed to support the foreach loop. If you're confident that create-7zip works fine for a single folder, you can substitute that for the cmd /c line above. Here's a listing of some handy example usages for 7zip on the command line.