Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
stubblyhead
Sep 13, 2007

That is treason, Johnny!

Fun Shoe

GPF posted:

And, Phone, Import-CSV and Get-Content were brought to us by $deity itself.

Yeah, the ease of reading from and writing to files is really nice. The more I use it, the more I like it to be honest. A project I'm working on is using a shitton of legacy VBScript, and I wish they would rework this poo poo to use PS instead for a variety of reasons. The biggest one being that the cscript/wscript engine has a totally sexy bug where it may not always return the exit code you specify in your script to the calling process.

Adbot
ADBOT LOVES YOU

DarthRoblox
Nov 25, 2007
*rolls ankle* *gains 15lbs* *apologizes to TFLC* *rolls ankle*...
Hi!

I'm completely new to Powershell, but I'm interesting in learning and I have a task that I'd like to automate. Basically, I need to run a series of SQL queries and then export all columns except the leftmost of each result to it's own Excel file with a slightly different set of headings. I'd then need it to save all of the files in a new folder in a directory, with the files titled like '[Date]_[a]_Import.xlsx'.

The structure would look like:
run SQL a, export to a.xlsx in xxx\[Date]_Imports
run SQL b, export to b.xlsx in xxx\[Date]_Imports
run SQL c, export to c.xlsx in xxx\[Date]_Imports

I can change the queries if removing the left column or reformatting the headings is too much, but I'm curious if this is doable with Powershell. Anyone feel like lending a hand?

adaz
Mar 7, 2009

Import-CSV is the poo poo, but Export-CSV is horrible piece of poo poo which I hate... until I had to write my OWN CSV import/export functions in VB.NET and goddamn did I miss powershell. It's really hard to write a correct parser for CSV files, they are the devils own work.

Viking_Helmet! Do you need excel or can they be CSVs? Because what you describe is pretty darn easy if it can be CSVs!

Also whoever was talking about not having enough Powershell projects at work my philosophy was always make myself projects if I had time. If there was a task I had to do at work that could be automated with powershell, automate it. My general experience has been that employers will see that, recognize it as a skill, and start to give you more projects of that nature.

adaz fucked around with this message at 01:26 on Mar 8, 2012

DarthRoblox
Nov 25, 2007
*rolls ankle* *gains 15lbs* *apologizes to TFLC* *rolls ankle*...
Sure, just checked and CSVs import fine.

Thanks!

adaz
Mar 7, 2009

Each SQL query is unique? How many are there? Is there any reason why you need to exclude the leftmost column as opposed to just not querying for that data?

To get started what I'd use is a function I wrote long ago and my normal method of avoiding export-CSV's... eccentricities. Yes it would be a glorious world where we could just pipe the DataSet to export-csv and it'd handle it gracefully... unfortunately that world doesn't exist.

code:
############
# SQL Data #
############
function Get-SqlData
{
param(
[parameter(Mandatory=$true,HelpMessage="SQL Server to connect to.")]
[string]$serverName,

[parameter(mandatory=$true,HelpMessage="SQL DB")]
[string]$databaseName,

[parameter(mandatory=$true,HelpMessage="SQL Query to run.")]
[string]$query
)
    $SQLDT = New-Object "System.Data.DataTable"
    $connString = "Server=$serverName;Database=$databaseName;Integrated Security=SSPI;"
    $da = New-Object "System.Data.SqlClient.SqlDataAdapter" ($query,$connString)
    [void]$da.fill($sqlDt)
    return $sqlDt
}
So as an example for how get-SqlData works and how you'd export it to CSV

code:

# Execute our SQL Query and store the data in the $queryResults variable.
$queryResults = Get-SqlData -server sqlserver -database databasename -query "select firstname,lastname from employees where lastname like 'd%'"

# Initialize our array which we will use to store then data and then
# to pipe to Export-CSv
$exportTable = @()

# add the result sets to the array
foreach($result in $queryResults) {
   # shorthand method of creating an object with two properties called 
   # firstname, lastname.
   $OutObj = "" | select firstname,lastname
   # set the properties on each object.
   $outObj.Firstname = $result.firstname
   $outObj.lastName = $result.Lastname
   #add the Object to our array for later exporting
   $exportTable += $outObj
}
# Export out to CSV
$exportTable | export-Csv C:\blah\blah.csv -noTypeInformation

With dates and so forth look at Get-Date and system.datetime class, should have all the functions you need for formatting your date/time string however you want.

adaz fucked around with this message at 01:44 on Mar 8, 2012

Recluse
Mar 5, 2004

Yeah, I did that.
I'm trying to get a list of servers (~400), their operating system version and all the groups/users in the local Administrators group and export it to a csv. I've modified a script to give me the list of servers and the operating system and export it, but having trouble getting a Get-WMIObject query on each server name for the local administrators group. Any ideas where to go from here?

code:
$LdapFilter = "(&(objectCategory=Computer)(operatingsystem=Windows Server*))"
 
$DirSearcher = New-Object System.DirectoryServices.DirectorySearcher($Null, $LdapFilter)
$DirSearcher.PageSize = 1000
 
$PropList = @("name","operatingSystem")
$DirSearcher.PropertiesToLoad.AddRange($PropList)
 
$DirSearcher.FindAll() | `
  Select-Object @{n='Name';e={ $_.Properties["name"] }},@{n='Operating System';e={ $_.Properties["operatingsystem"] }} |
  Export-Csv -NoTypeInformation "servers.csv"

DarthRoblox
Nov 25, 2007
*rolls ankle* *gains 15lbs* *apologizes to TFLC* *rolls ankle*...

adaz posted:

Each SQL query is unique? How many are there? Is there any reason why you need to exclude the leftmost column as opposed to just not querying for that data?

To get started what I'd use is a function I wrote long ago and my normal method of avoiding export-CSV's... eccentricities. Yes it would be a glorious world where we could just pipe the DataSet to export-csv and it'd handle it gracefully... unfortunately that world doesn't exist.

Well, the main reason I was hoping to exclude the leftmost column is because the (lengthy) query was written by someone else who didn't comment anything. However, after actually looking at it I found out that it's fairly simple and removing the column wasn't a problem.

The only difference between the queries is a "where" clause that's in a few different locations (select a where name='x', select a where name='y', select a where name='z')

Since the actual difference between queries is small, how hard would it be to make powershell loop through and replace each instance of x then y then z while still exporting each set of results to a csv?

RICHUNCLEPENNYBAGS
Dec 21, 2010

Viking_Helmet posted:

Hi!

I'm completely new to Powershell, but I'm interesting in learning and I have a task that I'd like to automate. Basically, I need to run a series of SQL queries and then export all columns except the leftmost of each result to it's own Excel file with a slightly different set of headings. I'd then need it to save all of the files in a new folder in a directory, with the files titled like '[Date]_[a]_Import.xlsx'.

The structure would look like:
run SQL a, export to a.xlsx in xxx\[Date]_Imports
run SQL b, export to b.xlsx in xxx\[Date]_Imports
run SQL c, export to c.xlsx in xxx\[Date]_Imports

I can change the queries if removing the left column or reformatting the headings is too much, but I'm curious if this is doable with Powershell. Anyone feel like lending a hand?

If you're using MS SQL Server, you can put FOR XML in your query. Probably not with other implementations.

Scaramouche
Mar 26, 2001

SPACE FACE! SPACE FACE!

Hey guys, I'm back to leeching off your expertise without ever contributing anything once again. I've got a bunch of product images are 500 pixels tall by (x) pixels wide. What I want to do is identify files where (x)<500 and then I want to 'pad out' the image file with white pixels (equally on either side) so it ends up being 500 x 500.

I'm know I can do this in Image Majick but would rather not install it on a production server (hundreds of thousands of images are involved), so I figured I'd ask you guys if it's possible in PowerShell. I know from reading around it's possible to resize things using WIA (http://blogs.msdn.com/b/powershell/archive/2009/03/31/image-manipulation-in-powershell.aspx), but it looks a bit daunting and was wondering if anyone had any experience doing it. I also can't find reference to padding the image instead of resizing it.

Jelmylicious
Dec 6, 2007
Buy Dr. Quack's miracle juice! Now with patented H-twenty!
Hmmm, that's an interesting one. The padding is harder than I thought, or at least, I couldn't find an option for it. (I tried cropping a negative amount of pixels, but that seems to error out.) Filtering is easy:

code:
$image = New-Object -ComObject Wia.ImageFile
$directory = $pwd   #set directory as current working directory, adjust as needed
$FilteredList = @() #empty array to add the images later
$ImageList = gci $directory/* -Include *.jpg   #add a -recurse for subfolders

ForEach($JPG in $ImageList)
    {
    $image.loadfile($JPG.versioninfo.filename)
    if ($image.width -lt 500)
        {
        $FilteredList += $JPG.versioninfo.Filename
        }
    }
This will return a Array of filenames you can use to manipulate the images later.

Only thing I could think of, is to have the script create an empty image, of $image.height * 500, and use the "stamp" filter to add the image over the blank one. See this MSDN page for an example in .NET.

Scaramouche
Mar 26, 2001

SPACE FACE! SPACE FACE!

Thanks for that. I actually have a .vbs script that can do it so I'm aware of the .NET solution, which goes exactly as you surmise. Create white 500x500 canvas, paste centered, and your uncle is bob. Was hoping to centralize around PowerShell and drop some of this array .vbs, .bat, .cmd files that have been following me around since the old days. I'm still pretty sure it's possible, just have to figure out how to access external libraries properly in PowerShell; I know the .NET syntax but am not sure how to reference it. Basically I want to be able to do:
code:
Using System.Drawing
But in PowerShell. Would it be something like this?
code:
[void]([reflection.assembly]::loadfile
("C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Drawing.dll"))
OR
[void]([reflection.assembly]::loadfile
("C:\Windows\Microsoft.NET\Framework\v2.0.50727\wiascr.dll"))
Sorry for the basic nature of the question but I've always been using the 'built in' functionality of PS until this point.

EDIT-ugh stupid question didn't notice your WIA call in the example code until I tried to run it just now. Embarrassing.

Scaramouche fucked around with this message at 01:40 on Mar 13, 2012

angrytech
Jun 26, 2009
I've got a bunch of computer objects in AD that are containers containing sub-objects, and I'm having a problem trying to pull the sub-objects out. I've tried get-adcomputer and get-adobject in conjunction with get-childitem, but I apparently don't know the right magic.
Can anyone suggest another way to attack this?

Jelmylicious
Dec 6, 2007
Buy Dr. Quack's miracle juice! Now with patented H-twenty!
On the subject of really using .NET, I am only a noob at that, I think Adaz or someone else will be better suited to answer that. And Angrytech: what properties are you trying to get from the computer object? Have youtried simply calling $_.propertyname or used get-adcomputer with the -property flag? Have you checked the Technet page on get-adcomputer

angrytech
Jun 26, 2009

Jelmylicious posted:

On the subject of really using .NET, I am only a noob at that, I think Adaz or someone else will be better suited to answer that. And Angrytech: what properties are you trying to get from the computer object? Have youtried simply calling $_.propertyname or used get-adcomputer with the -property flag? Have you checked the Technet page on get-adcomputer

From what I can tell, the problem is that the sub-object isn't actually a property, so the property flag won't get me what I want.

adaz
Mar 7, 2009

I actually just recently was working with a bunch of image conversion stuff in powershell. Maybe this will help? It's a resize-JPEG function that returns a byte array (it's designed for loading thumbnail photos into Active Directory) but it might give you a head start on your project. Gives you an example of how to use the system.drawing stuff.

code:
Function Resize-Jpeg {
param($path)

    $fileInfo = get-ChildItem $path
    $oldJpeg = new-Object system.drawing.bitmap $path
    
    # we need to resize our jpegs to be 300 by x where x is whatever the proper ratio is depending on if the jpeg is size
    # height or width wise in dimension.
    
    If($oldjpeg.height -lt $oldjpeg.width) {
        $factor = $oldjpeg.height / $oldjpeg.width
        [int]$newHeight =  300 * $factor
        [int]$newWidth = 300
    } else {
        $factor = $oldjpeg.width / $oldjpeg.height
        [int]$newWidth = 300 * $factor
        [int]$newHeight = 300
    }
    $thumbNail = $oldJpeg.GetThumbnailImage($newWidth,$newHeight,$null,[intptr]::zero)
    $encoderParams = New-Object System.Drawing.Imaging.EncoderParameters(1) 
    $qualityEncoder = [System.Drawing.Imaging.Encoder]::Quality
    $encoderParams.Param[0] = New-Object System.Drawing.Imaging.EncoderParameter($qualityEncoder, 75)
    $CodecInfo = [System.Drawing.Imaging.ImageCodecInfo]::GetImageEncoders()|where {$_.MimeType -eq 'image/jpeg'}    
    $thumbnail.save("c:\temp\testthumb.jpg",$codecInfo,$($encoderParams))
    
    return [byte[]]$file = Get-Content "c:\temp\testthumb.jpg" -Encoding Byte
    
}
AngryTech you're wanting to access child objects on an AD object right? The best thing to do is to say gently caress you get-ad* cmd-lets and use the base .net classes. Actually, this is what I'm going to say since I don't like the cmdlets and prefer to use the base .NET classes. I'm sure it's possible using the new cmdlets!

As an example to access children on an AD object using the base .NET classes, here is the basic code I used. We're looking at the children of a DC and the screenshot is showing an example of such. Works the same for an OU, etc. If you wanted to iterate through them use a foreach loop.

code:
$adObj = [adsi]"LDAP://CN=Blah,ou=blah,ou=blah,dc=blah,dc=com"
$adObj.Children

# iterate through the children
foreach($child in $adobj.children) {
  $child # do stuff
}

adaz fucked around with this message at 19:14 on Mar 13, 2012

Scaramouche
Mar 26, 2001

SPACE FACE! SPACE FACE!

Thanks Adaz, think I got it mostly figured out. I just needed to get onto the right new-Object x.y.z syntax before I could start hacking around. After that it's trivial to re-word the .vbs script. If I can get it cleaned up I'll try to post it here.

Recluse
Mar 5, 2004

Yeah, I did that.
I'm now trying to get a list of all server's current time zone settings as we may have had a few that had the wrong ASI installed. Testing this line by line works, but when it gets down to the $timezone part, it's giving me the following:

Powershell posted:

Name
----
SERVERNAME01
Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At line:4 char:25
+ $timezone=(Get-WmiObject <<<< Win32_timezone -computername $Server).caption
+ CategoryInfo : InvalidOperation: (: ) [Get-WmiObject], COMException
+ FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand

SERVERNAME02
Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At line:4 char:25
+ $timezone=(Get-WmiObject <<<< Win32_timezone -computername $Server).caption
+ CategoryInfo : InvalidOperation: (: ) [Get-WmiObject], COMException
+ FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand

Changing $Server to SERVERNAME01 in the script it works fine--any idea what I'm doing wrong?

code:
$LdapFilter = "(&(objectCategory=Computer)(operatingsystem=Windows Server*))" 
$DirSearcher = New-Object System.DirectoryServices.DirectorySearcher($Null, $LdapFilter)
$DirSearcher.PageSize = 1000
$PropList = @("name")
$DirSearcher.PropertiesToLoad.AddRange($PropList)
$Servers=$DirSearcher.FindAll() | Select-Object @{n='Name';e={$_.Properties["name"]}}

ForEach($Server in $Servers)
{
$Server
$timezone=(Get-WmiObject Win32_timezone -computername $Server).caption
$timezone
}

Nebulis01
Dec 30, 2003
Technical Support Ninny
Stupid question

We have a server that I have to backup using powershell and robocopy because it is still stuck on Server 2003 SP1. I have the following script and it runs just fine but I'd like to add some error detection. Would it be possible to have the script return an email of robocopy returned error level 1 or something similar?

code:
 
$Today = (Get-Date -format "yyyy-MM-dd")
$targetFolder = "\\BACKUP\backups$\APP10\FlatFile"
$backupDir = "$targetFolder\$Today"

function Remove-Items
{ 
 $testFolderPath = $targetFolder
 if (Test-Path -Path $testFolderPath)
   { 
     $fiveDaysAgo = (Get-Date).AddDays(-5)        
     Get-ChildItem -Path $testFolderPath -Recurse | Where-Object { $_.CreationTime -lt $fiveDaysAgo } | Remove-Item -recurse -force
    }
 else 
   {
    Write-Host "$testFolderPath does not exist."
    #Kill Script
    Exit
   }
 }
 
function Send-Email
{
	$emailFrom = "APP10Backup@somewhere.lan"
	$emailTo = "sysadmins@somewhere.lan"
	$subject = "Backup Completed Sucessfully"
	$body = "APP10 was backed up successfully "
	$smtpServer = "exch.somewhere.lan"
	$smtp = new-object Net.Mail.SmtpClient($smtpServer)
	$smtp.Send($emailFrom, $emailTo, $subject, $body)
}

function Create-Folders 

 { 
    if (Test-Path -Path $backupDir) 
     { 
         #do nothing. Folders have been setup already
    }
    else 
     {
        md "$backupDir" -force
    }
 }
 
 
 
 
# Remove Folders older than $fivedaysago

Remove-Items


# Start backup operation

Create-Folders


Robocopy /MIR /Z /COPYALL /R:5 /W:2 /NP /TEE "C:\Documents and Settings" "$backupDir\c\Documents and Settings" /LOG+:"$backupDir\backup.log" 

Robocopy /MIR /Z /COPYALL /R:5 /W:2 /NP /TEE "C:\Inetpub" "$backupDir\c\Inetpub" /LOG+:"$backupDir\backup.log"

Robocopy /MIR /Z /COPYALL /R:5 /W:2 /NP /TEE "C:\usr" "$backupDir\c\usr" /LOG+:"$backupDir\backup.log"

Robocopy /MIR /Z /COPYALL /R:5 /W:2 /NP /TEE "G:\dev" "$backupDir\g\dev" /LOG+:"$backupDir\backup.log"

Robocopy /MIR /Z /COPYALL /R:5 /W:2 /NP /TEE "G:\ifas" "$backupDir\g\ifas" /LOG+:"$backupDir\backup.log"

Robocopy /MIR /Z /COPYALL /R:5 /W:2 /NP /TEE "G:\media" "$backupDir\g\media" /LOG+:"$backupDir\backup.log"

Robocopy /MIR /Z /COPYALL /R:5 /W:2 /NP /TEE "G:\migdir" "$backupDir\g\migdir" /LOG+:"$backupDir\backup.log"

Robocopy /MIR /Z /COPYALL /R:5 /W:2 /NP /TEE "G:\mfaslmf" "$backupDir\g\mfaslmf" /LOG+:"$backupDir\backup.log"

Robocopy /MIR /Z /COPYALL /R:5 /W:2 /NP /TEE "G:\sbi" "$backupDir\g\sbi" /LOG+:"$backupDir\backup.log"

Robocopy /MIR /Z /COPYALL /R:5 /W:2 /NP /TEE "G:\SystemState" "$backupDir\g\SystemState" /LOG+:"$backupDir\backup.log" 

# Send an email telling somebody this script ran successfully

Send-Email 

adaz
Mar 7, 2009

Recluse

$Server is just the ADobject you're retrieving, you need to access the property (name). Take a looksee at screenshot but you need to replace $server with $server.name



Nebulis01

Short answer: yes

Long answer: maybe

You can encapsulate that entire thing in a try/catch block and then call a send-email function (I posted one a page or so back) when powershell encounters a terminating error. The problem i've had before with using third party utilities - such as robocopy - is they might error out and powershell probably will have no idea unless they are throwing a terminating error which is rare. It will, however, catch when a powershell function or cmdlet encounters an error. What i've done in the past when using robocopy inside powershell is to log it and have powershell email me the logs, then check those. Here are some examples

Try/Catch block
code:
try {
 # put code here
} catch {
     $smtp = new-object Net.Mail.SmtpClient("smtp server here")
    $msg = new-Object Net.Mail.MailMessage
    $msg.From = "email address here"
    $msg.body = "body here  -- error will be stored in the $error variable" 
    $msg.To.Add("emailto here")
    $msg.Subject = "subject" 
    $smtp.Send($msg)
}
Robocopy send the log file
code:
$smtp = new-object Net.Mail.SmtpClient("smtp.server")
$smtp.UsedefaultCredentials = $true

$msg = new-Object Net.Mail.MailMessage
$msg.From = "blah@contoso.com"
$msg.body = "Words and stuff" 
$msg.To.Add("blah@contoso.com")
$att = new-Object Net.Mail.Attachment(C:\path\To\Log.File)
$msg.Attachments.Add($Att)
$msg.Subject = "Subject" 
$smtp.Send($msg)

adaz fucked around with this message at 19:48 on Mar 14, 2012

Nebulis01
Dec 30, 2003
Technical Support Ninny
adaz, thanks. I'll give that some testing :)

angrytech
Jun 26, 2009

adaz posted:

I actually just recently was working with a bunch of image conversion stuff in powershell. Maybe this will help? It's a resize-JPEG function that returns a byte array (it's designed for loading thumbnail photos into Active Directory) but it might give you a head start on your project. Gives you an example of how to use the system.drawing stuff.

code:
Function Resize-Jpeg {
param($path)

    $fileInfo = get-ChildItem $path
    $oldJpeg = new-Object system.drawing.bitmap $path
    
    # we need to resize our jpegs to be 300 by x where x is whatever the proper ratio is depending on if the jpeg is size
    # height or width wise in dimension.
    
    If($oldjpeg.height -lt $oldjpeg.width) {
        $factor = $oldjpeg.height / $oldjpeg.width
        [int]$newHeight =  300 * $factor
        [int]$newWidth = 300
    } else {
        $factor = $oldjpeg.width / $oldjpeg.height
        [int]$newWidth = 300 * $factor
        [int]$newHeight = 300
    }
    $thumbNail = $oldJpeg.GetThumbnailImage($newWidth,$newHeight,$null,[intptr]::zero)
    $encoderParams = New-Object System.Drawing.Imaging.EncoderParameters(1) 
    $qualityEncoder = [System.Drawing.Imaging.Encoder]::Quality
    $encoderParams.Param[0] = New-Object System.Drawing.Imaging.EncoderParameter($qualityEncoder, 75)
    $CodecInfo = [System.Drawing.Imaging.ImageCodecInfo]::GetImageEncoders()|where {$_.MimeType -eq 'image/jpeg'}    
    $thumbnail.save("c:\temp\testthumb.jpg",$codecInfo,$($encoderParams))
    
    return [byte[]]$file = Get-Content "c:\temp\testthumb.jpg" -Encoding Byte
    
}
AngryTech you're wanting to access child objects on an AD object right? The best thing to do is to say gently caress you get-ad* cmd-lets and use the base .net classes. Actually, this is what I'm going to say since I don't like the cmdlets and prefer to use the base .NET classes. I'm sure it's possible using the new cmdlets!

As an example to access children on an AD object using the base .NET classes, here is the basic code I used. We're looking at the children of a DC and the screenshot is showing an example of such. Works the same for an OU, etc. If you wanted to iterate through them use a foreach loop.

code:
$adObj = [adsi]"LDAP://CN=Blah,ou=blah,ou=blah,dc=blah,dc=com"
$adObj.Children

# iterate through the children
foreach($child in $adobj.children) {
  $child # do stuff
}


Thanks dude, this did exactly what I need. :cheers:

stubblyhead
Sep 13, 2007

That is treason, Johnny!

Fun Shoe
Getting an unexpected error with a script I've used successfully on other servers without any problems:

code:
$password =  ConvertTo-SecureString "fakepassword" -AsPlainText -Force
ConvertFrom-SecureString $password | Set-Content c:\passwordfile.txt
(I know, -AsPlainText is not ideal, but for various reasons I can't do this interactively)

Anyway, I get the following error:

ConvertFrom-SecureString: The system cannot find the file specified

Some googling implies that this might be a UAC thing, can anyone confirm? I don't think it's related to c:\passwordfile.txt, since I would expect an error to be thrown on Set-Content in that case.

adaz
Mar 7, 2009

Not sure if it's UAC or not. With UAC turned off everything works fine. UAC turned on I get some errors about writing to the root of C:\, if I change it to C:\temp\blah (or whatever your environment has set as the temp dir) it works fine. Try writing to temp or like ENV:\Temp and see if it'll work for you but I was unable to replicate the exact error you're getting.

We don't have UAC turned on on our servers though, so I was just testing with Windows 7 instead of server 2k8 which might explain some of the discrepancies. The other thing I guess it could be is if C:\ isn't on one of your servers for some reason. Are you powershell remoting to the servers? Do any of your servers not have a C:\ drive for some reason (for instance, some of ours don't if they are citrix boxes)?

adaz fucked around with this message at 18:25 on Mar 15, 2012

Nebulis01
Dec 30, 2003
Technical Support Ninny

stubblyhead posted:

Getting an unexpected error with a script I've used successfully on other servers without any problems:

code:
$password =  ConvertTo-SecureString "fakepassword" -AsPlainText -Force
ConvertFrom-SecureString $password | Set-Content c:\passwordfile.txt
(I know, -AsPlainText is not ideal, but for various reasons I can't do this interactively)

Anyway, I get the following error:

ConvertFrom-SecureString: The system cannot find the file specified

Some googling implies that this might be a UAC thing, can anyone confirm? I don't think it's related to c:\passwordfile.txt, since I would expect an error to be thrown on Set-Content in that case.

Unless you're running as admin in 7/2008R2 with UAC enabled. You won't be able to write to the root of a drive, it's a security thing. Try ENV:\temp or something else?

edit: damnit adaz, you're quick

Jelmylicious
Dec 6, 2007
Buy Dr. Quack's miracle juice! Now with patented H-twenty!
Could very well be a UAC error, since server 2008 doesn't like you putting things in the C:\ root. Either put it in a folder or elevate your powershell.

adaz
Mar 7, 2009

Nebulis01 posted:

edit: damnit adaz, you're quick

Heh it's the lunch hour was just checking threads!

stubblyhead
Sep 13, 2007

That is treason, Johnny!

Fun Shoe
I'm sorry, I was a little extreme in my script sanitizing. I'm writing my file to a directory, not the the root. The path definitely exists, but regardless if it were an issue creating that file wouldn't the error get thrown on Set-Content? I have some additional error text too that will probably be helpful, but I had to jump back on a vpn which blocks sa. I'll try to remember to post later.

e: Just realized I can ssh to home and get to the forums that way. Here's the full output:


code:
At C:\temp\f40ee6ff-e305-417d-9aac-6b2221edaa8c.ps1:3 char:25

+ ConvertFrom-SecureString <<<<  $password | Set-Content C:\myDirectory\credentials.txt
    + CategoryInfo          : NotSpecified: (:) [ConvertFrom-SecureString], CryptographicException
    + FullyQualifiedErrorId : System.Security.Cryptography.CryptographicException,Microsoft.PowerShell.Commands.ConvertFromSecureStringCommand

stubblyhead fucked around with this message at 18:39 on Mar 15, 2012

adaz
Mar 7, 2009

SecureString and convert-SecureString requires you to use the same user account to decrypt the password as you used to encrypt it. Are you encrypting the save file with another user account then running it on the server under a different account?

stubblyhead
Sep 13, 2007

That is treason, Johnny!

Fun Shoe

adaz posted:

SecureString and convert-SecureString requires you to use the same user account to decrypt the password as you used to encrypt it. Are you encrypting the save file with another user account then running it on the server under a different account?

This is the script which is going to create that encrypted file to be used later; there's no decryption happening at all in this script. The very same script has worked without error on other servers, but I have limited visibility to see what kind of settings might be different on this one compared to those.

Recluse
Mar 5, 2004

Yeah, I did that.

adaz posted:

Recluse

$Server is just the ADobject you're retrieving, you need to access the property (name). Take a looksee at screenshot but you need to replace $server with $server.name




Excellent, worked great, thank you!

adaz
Mar 7, 2009

stubblyhead posted:

This is the script which is going to create that encrypted file to be used later; there's no decryption happening at all in this script. The very same script has worked without error on other servers, but I have limited visibility to see what kind of settings might be different on this one compared to those.

If that's the case I'm guessing it is going to be something more esoteric, perhaps a different version of .NET? Are the servers you're having the issue on older/newer/have anything at all in common? Does your account not have admin permissions on those servers?

stubblyhead
Sep 13, 2007

That is treason, Johnny!

Fun Shoe

adaz posted:

If that's the case I'm guessing it is going to be something more esoteric, perhaps a different version of .NET? Are the servers you're having the issue on older/newer/have anything at all in common? Does your account not have admin permissions on those servers?

I'm going to go with 'esoteric' as well. The account I'm using is an enterprise admin, so it should be able to do anything it wants on that server. That's one of the reasons I can't do this interactively actually--I'm not permitted to log in to the remote server with my personal account, and I can only use that admin account in automation scripts and crap like that. So basically I have the whole thing wrapped up into a process that runs powershell on the remote server (authenticating as the admin user) and executes the script.

It's a moot point anyway though. I finally just asked one of my colleagues with greater access to do it for me. Same script worked perfectly logged into the server as that user, so I don't know what the gently caress. Hopefully I'll be able to actually read it as a secure string later on.

adaz
Mar 7, 2009

stubblyhead posted:

I'm going to go with 'esoteric' as well. The account I'm using is an enterprise admin, so it should be able to do anything it wants on that server. That's one of the reasons I can't do this interactively actually--I'm not permitted to log in to the remote server with my personal account, and I can only use that admin account in automation scripts and crap like that. So basically I have the whole thing wrapped up into a process that runs powershell on the remote server (authenticating as the admin user) and executes the script.

It's a moot point anyway though. I finally just asked one of my colleagues with greater access to do it for me. Same script worked perfectly logged into the server as that user, so I don't know what the gently caress. Hopefully I'll be able to actually read it as a secure string later on.

Is your account actually blocked from logging into the server via GPO or something not just like a IT policy? If that's the case that would explain it. The secure cmdlets actually require a profile to be created and for the given user to "log onto" the machine before they will work. I ran into it before when doing scheduled tasks with cmdlets and secure strings, since the profile wasn't loaded I got a generic cryptographic error.

If this is the case it won't be able to decrypt it when the script runs as the account trying to do the decryption still wouldn't be able to log on to use the cryptographic provider on the machine.

adaz fucked around with this message at 00:33 on Mar 16, 2012

stubblyhead
Sep 13, 2007

That is treason, Johnny!

Fun Shoe

adaz posted:

Is your account actually blocked from logging into the server via GPO or something not just like a IT policy? If that's the case that would explain it. The secure cmdlets actually require a profile to be created and for the given user to "log onto" the machine before they will work. I ran into it before when doing scheduled tasks with cmdlets and secure strings, since the profile wasn't loaded I got a generic cryptographic error.

If this is the case it won't be able to decrypt it when the script runs as the account trying to do the decryption still wouldn't be able to log on to use the cryptographic provider on the machine.

Hmm, interesting... my personal account is not in the remote users for that machine, but the service account is--I'm just barred from using it that way by IT policy. I'm spawning that powershell process in such a way that the target server doesn't even know my personal account exists, but it's entirely possible that the service account didn't have a profile on this server. I was able to decrypt that file and use it in a credentials object though. My friend remoted in using the service account, so if it was a matter of the profile not existing that would have fixed it.

Red_Fred
Oct 21, 2010


Fallen Rib
Cross posting this from the Windows software megathread.

I have a quick question about making a batch file to rename some files.

I have to scan a bunch of files for my job. They need to be renamed to 'Scanned As At [DATE][Number]'. I played around with the ren function to get this to work but ultimately could not. The files come from the scanner as seemingly random numbers E.g. "3526346.pdf" & "3526347.pdf" should be renamed to "Scanned As At 16-03-12.pdf" & "Scanned As At 16-03-12 (1).pdf".

An awesome bonus would be if they could then be put in to a folder with the same name, but multiples just in the same folder.

Is this possible?

peak debt
Mar 11, 2001
b& :(
Nap Ghost
It's certainly possible, Powershell is a full programming language. Something on the basis of

code:
ls (*.pdf) | % {
  $newname = ("Scan " + $_.CreationTime.Day + "-" + $_.CreationTime.Month + "-" + $_.CreationTime.Year)
  while (test-path $newname) {
    $newname = $newname + "1"
  }
  mv $_.Name $newname
}

Dreadite
Dec 31, 2004

College Slice

adaz posted:

Whoops, missed this -- did you ever figure it out? At a casual glance it looks like everything is right but what type of right are you setting? deny? modify? allow? or something more esoteric?

Late response- but I did figure this out. There are some underlying permissions changes that needed to be added- namely inheritance and propagation flags that without, explorer only identifies the permission set as "special permissions". I suppose there may be underlying octal permissions or something that didn't properly line up with the values explorer was expecting to see in order to assign a normal read, write, or execute permission. (This is just how I rationalized it in my brain)

The code that I ended up using looked like this:

code:
#variables to set propagations rules for "This folder, subfolders, and files"
$inherit1 = [system.security.accesscontrol.InheritanceFlags]"ContainerInherit, ObjectInherit"
$inherit2 = [system.security.accesscontrol.InheritanceFlags]"none"
$propagation = [system.security.accesscontrol.PropagationFlags]"None"
and something like this

code:
$acl=Get-Acl F:\test1
$permission1 ="$ftpuser", "Modify", $inherit1, $propagation, "allow"
$accessrule1 = New-Object system.Security.AccessControl.FileSystemAccessRule $permission1
$acl.setaccessrule($accessrule1)
$acl | Set-Acl F:\test1

adaz
Mar 7, 2009

Glad to hear that Dreadite.

As a note, and I missed this last week, but the beta of powershell 3.0 is out: http://www.microsoft.com/download/en/details.aspx?id=28998

Changes are fairly minor as far as breaking backwards compatibility, I haven't had a chance to test out the new features.

quote:


Workflows that run long-running activities (in sequence or in parallel) to perform complex, larger management tasks, such as multi-machine application provisioning. Using the Windows Workflow Foundation at the command line, Windows PowerShell workflows are repeatable, parallelizable, interruptible, and recoverable.

Robust sessions that automatically recover from network failures and interruptions and allow you to disconnect from the session, shut down the computer, and reconnect from a different computer without interrupting the task.

Scheduled jobs that run regularly or in response to an event.

Commands that can be executed with a delegated set of credentials so users with limited permissions can run critical jobs

Simplified language syntax that make commands and scripts look a lot less like code and a lot more like natural language.

Improved cmdlet discovery and automatic module loading that make it easier to find and run any of the cmdlets installed on your computer.

Show-Command, a cmdlet and ISE Add-On that helps users find the right cmdlet, view its parameters in a dialog box, and run it.

Jelmylicious
Dec 6, 2007
Buy Dr. Quack's miracle juice! Now with patented H-twenty!
Ooh, I really should try out that Beta! Thanks for the link.

Adbot
ADBOT LOVES YOU

Jelmylicious
Dec 6, 2007
Buy Dr. Quack's miracle juice! Now with patented H-twenty!
Sorry to double post, but this is just too awesome. The new ISE is way more usable! No more seperated input and output pane is good. But the best thing is the syntax checking. Forgot to close some parenthesis? It will highlight your dangling one:



Woohoo! It does the same thing in the powershell pane in ISE. Try putting in the following (which just feels wrong to leave like this)
code:
$string = "text
The highlighting while typing is a bit distracting, especially since any variable you type starts bright red. Red -eq error, damnit! I do like that you can now fold your script blocks. I only wish it would auto highlight all instances of a variable when you select it, but you can't have everything.

Jelmylicious fucked around with this message at 13:35 on Mar 22, 2012

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply