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
adaz
Mar 7, 2009

intellisense to the IDE? oh my god yes, yes yessssssssssssssssssssss

Adbot
ADBOT LOVES YOU

Thrawn200
Dec 13, 2008

"Sometimes I think the surest sign that intelligent life exists elsewhere in the universe is that none of it has tried to contact us." - Calvin & Hobbes
Start out by saying I'm still absolutely a PowerShell novice, still learning a lot of the basics. So feel free to laugh at me if I have something horribly wrong.

Part of my work study is packaging software for silent deployment and I'm trying to start using PowerShell to do it. I'm mostly having success but trying to deploy it with SCCM 2012 gives me an error when the script gets run. I wanted to have someone who knows what they are doing look at my simple PowerShell script to make sure I don't have it screwed up before I dig too deep into seeing if it's a SCCM issue and not just my poor PowerShell knowlege.

In this case it's just simply copying some files over and copying some shortcuts, nothing to run. My next step is to also learn how to use the equivalents in PowerShell to stuff that I'm used to using in batch files instead of my messy Get-Location stuff. (Like %SYSTEMDRIVE%, ~dp0% etc...)

code:
$path = Get-Location

$file = "Mango RTMTK Advanced"
Copy-Item "$path\$file" "C:\Windows Phone 7.5 Training Kit\Mango RTMTK Advanced\" -recurse -force

$file2 = "Mango RTMTK Basic"
Copy-Item "$path\$file2" "C:\Windows Phone 7.5 Training Kit\Mango RTMTK Basic\" -recurse -force

New-Item "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Windows Phone Training" -type directory -force

$file3 = "Windows Phone 7.5 Basic Training.lnk"
Copy-Item "$path\$file3" "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Windows Phone Training\" -force

$file4 = "Windows Phone 7.5 Advanced Training.lnk"
Copy-Item "$path\$file4" "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Windows Phone Training\" -force
I get an error saying that "The term 'C:\whatever\$path\is' is not recognized as the name of a cmdlet, function, script file, or operable program."

adaz
Mar 7, 2009

There's nothing wrong with the syntax that I can see, assuming the path and location actually exist. Based on the error you're getting it almost seems as though there might be a directory or file or something that has a character that needs to be escaped out. You could also be missing a " omewhere in the script is the other common time you'll get that error. You are sure get-location is returning the correct value when SCCM runs the script, not some crazy weird temps systemdir when it executes the script? I mean you can add some quick logging like the example below to verify.

code:
$path = get-location
$path >> C:\temp\location.txt
Also the equivalents to most of that stuff you're talking about in batch files can be found by doing a cd ENV: and then a dir, just as a quick and easy reference although there are plenty more. So ENV:SystemDrive is the system dir.

adaz fucked around with this message at 18:39 on Mar 26, 2012

stubblyhead
Sep 13, 2007

That is treason, Johnny!

Fun Shoe

Thrawn200 posted:

I get an error saying that "The term 'C:\whatever\$path\is' is not recognized as the name of a cmdlet, function, script file, or operable program."

Is this a typo on your part, or is that actually in the error message?


adaz posted:

Also the equivalents to most of that stuff you're talking about in batch files can be found by doing a cd ENV: and then a dir, just as a quick and easy reference although there are plenty more. So ENV:SystemDrive is the system dir.

Neat, I didn't know you could do this. Have a technet link or something for some further reading?

adaz
Mar 7, 2009

Get-Help about_environment_variables is a decent overview, but - as as always - the hey scripting guy article(s) are better for practical examples. http://blogs.technet.com/search/searchresults.aspx?q=environment%20variables&sections=7618

Exclusive
Jan 1, 2008

PowerShell gurus... I have a simple task that I can't quite get to work. So I want to delete a network folder and all files/sub-dirs. Occasionally this will give me errors, whether it be permissions or path too long. That's fine -- I will just rename the top-level folder and deal with it separately.

I tried to "catch" the errors but when I run this sample it just pukes all the errors and never executes the code in the catch block. Am I doing something wrong?

code:
$deadUser = "username"

write-host "Attempting to delete \\server\users\$deadUser `n"

try {
Remove-Item "\\server\users\$deadUser" -Recurse
}
catch {
	write-host "Cannot delete. Renaming to \\server\users\xxxdead" + $deadUser + "`n"
	Rename-Item -Path "\\server\users\$deadUser" -NewName ("xxxdead" + $deadUser)
}

adaz
Mar 7, 2009

Catch only catches terminating errors, non-terminating errors won't ever be caught by the catch block by default. Iff the cmdlet itself handles terminating errors, which quite a few do including remove-item, it won't pass them to the try/catch block unless you change how the cmdlet handles errors via it's -errorAction or whatever parameter.

So, documentation wise see about_try_catch_finally: http://technet.microsoft.com/en-us/library/dd315350.aspx

You can also globally set the $erroractionpreference to "stop", that will make every error on everything terminating... with some rare exceptions mainly contained in the COM interface that hopefully you never run into.

adaz fucked around with this message at 17:45 on Mar 27, 2012

Exclusive
Jan 1, 2008

adaz posted:

Catch only catches terminating errors, non-terminating errors won't ever be caught by the catch block by default.

Thanks for the help -- clears everything up. I added "-ErrorAction stop" to my Remove-Item statement and I'm good to go.

Dreadite
Dec 31, 2004

College Slice
Alright guys I'm back- I feel stupid because every time I write a script that needs to use some real programming concepts- like not just using built in cmdlets to add features to a server or moving users around in AD, I get in over my head. I suppose this is all part of the learning experience here.

Let me explain what I need to accomplish- When a user logs into my server, I need to check what group they are in, and according to the group they are in, I need to modify a .url shortcut on their desktop to point to a different location. There is a template .url shortcut in allusers/desktop to reference.

After a bunch of google-fu, it seems like in order to do this I need to utilize a WshShell Object, as Powershell doesn't seem to be able to do this natively. I've pieced together and modified some code examples from various blogs, but I don't even know if my if-else if structure is the correct way to do things programatically. Mostly I just need a sanity check and perhaps someone knows a cleaner way to do this.

code:
$Currentuser = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$windowsprincipal = New-Object System.Security.Principal.WindowsPrincipal($Currentuser)

if($windowsprincipal.isinrole("usersgroup1"))
{
$sourcepath = "C:\Documents and Settings\All Users\Desktop\shortcutdestination"
$destination = ($env:USERPROFILE + "C:\Documents and Settings\" + "\Desktop\mylink.url")
Copy-Item $sourcepath $destination
$shell = New-Object -COM WScript.Shell
$shortcut = $shell.CreateShortcut($destination)
$shortcut.TargetPath = "http://server/application"
$shortcut.Description = "application_name"
$shortcut.Save()
}
elseif($windowsprincipal.isinrole("usersgroup2"))
{
$sourcepath = "C:\Documents and Settings\All Users\Desktop\shortcutdestination"
$destination = ($env:USERPROFILE + "C:\Documents and Settings\" + "\Desktop\mylink.url")
Copy-Item $sourcepath $destination
$shell = New-Object -COM WScript.Shell
$shortcut = $shell.CreateShortcut($destination)  
$shortcut.TargetPath = "http://server2/application"  
$shortcut.Description = "application_name"  
$shortcut.Save()
}

Jelmylicious
Dec 6, 2007
Buy Dr. Quack's miracle juice! Now with patented H-twenty!
This seems to be in the wrong order:
code:
$destination = ($env:USERPROFILE + "C:\Documents and Settings\" + "\Desktop\mylink.url")
Also, never tried to use an elseif. It should work, but I always prefered switch for those things.

Mully Clown
Aug 1, 2004

I handle my piss like the great big frilly girls blouse that I am
I think you're trying to achieve the same end result as this.
code:
$destination =  "$env:userprofile\desktop\mylink.url"
Also looks like the perfect job for group policy preferences.

Dreadite
Dec 31, 2004

College Slice

Mully Clown posted:

I think you're trying to achieve the same end result as this.
code:
$destination =  "$env:userprofile\desktop\mylink.url"
Also looks like the perfect job for group policy preferences.

Yeah this is an exercise in futility. I just made a simpler script to copy the shortcut from a network location applied as a logon script at the group OU level in GP. This actually works and is much easier. :psyduck:

Edit: sometimes you just think "this is maybe a cool way to get better at powershell" but man what a waste of an hour

Jelmylicious
Dec 6, 2007
Buy Dr. Quack's miracle juice! Now with patented H-twenty!

Dreadite posted:

I just made a simpler script to copy the shortcut from a network location applied as a logon script at the group OU level in GP.

Since 2008 you can add shortcuts directly through Group Policy Preferences. And you can put it all in one policy and have it select the right one through Item Level Targeting.

Anyway, don't discount your hour fiddling with this, practice with powershell is always valuable! Even when it won't pan out. Part of the process is knowing when you should or shouldn't use PS.

Siets
Sep 19, 2006

by FactsAreUseless
I need some help with NTFS AD permissions. (I refuse to go back to ICACLS. :argh:)

I've got a script that makes a folder. I now want to set an AD user account to have full control to that folder, all subfolders, and files. The problem I'm running into is that these permissions are only set for "This folder only" and aren't being inherited.

So I know that I need to specify inheritance settings as well. I'm just wondering how to go about it. I can't seem to find anywhere on MSDN how these methods want their input (quite possible I just don't know how to look things up properly on MSDN.)

Here's what I have currently, which produces the folder with permissions only to the folder and nothing else:

code:
# Sets Full Control on the user's directory
$permUser = "AD\$userID","FullControl","Allow"
$ruleUser = New-Object System.Security.AccessControl.FileSystemAccessRule $permUser

# Gets the folder's ACL and applies then applies the rule
$Acl = Get-Acl "<user folder>"
$Acl.AddAccessRule($ruleUser)
$Acl | Set-Acl "<user folder>"
Easy enough. Now for inheritance, I've done a little research and I think this is what I need to be using to set it:

code:
$permInherit = <oh god what goes here!??!?>
$ruleInherit = New-Object System.Security.AccessControl.InheritanceFlags $permInherit

$Acl.AddAccessRule($ruleUser,$ruleInheritance) <is this the correct application of the rule???>
Again, I suck at looking things up on MSDN. I don't know what System.Security.AccessControl.InheritanceFlags actually needs for an input. I only lucked out FileSystemAccessRule because a lot of people have blogged about it at this point and there were several examples to work from. Funny that no one else seems to have run into issues with inheritance though! :eng99:

Side question: Do I want to be using the $Acl.AddAccessRule method or $Acl.SetAccessRule method? Does it matter? Does using "Set" override existing rules on the ACL object? That was my assumption since "Add" just seems to append the rule to the existing rules.

e: vvv Thanks man! I'll give this a shot right now. Also, it looks like we weren't the only ones upset with MS's veiled inheritance rules (check the bottom post haha.)

Siets fucked around with this message at 21:09 on Mar 29, 2012

Dreadite
Dec 31, 2004

College Slice
Hey whoa, I get to be helpful here. Siets, look at my last few posts in this thread, I was dealing with the exact same thing. You need to set your propagation and inheritance flags properly.

http://forums.somethingawful.com/showthread.php?threadid=3286440&userid=0&perpage=40&pagenumber=11#post401783499

edit: I think this was the page that pointed me in the right direction.

http://developers.de/blogs/damir_dobric/archive/2007/06/18/directory-security-and-access-rules.aspx

Dreadite fucked around with this message at 20:56 on Mar 29, 2012

stubblyhead
Sep 13, 2007

That is treason, Johnny!

Fun Shoe

adaz posted:

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.

Sorry to quote from so far back, but good lord you are not kidding about this cmdlet. I have a multi-line comma-delimited string, you stupid piece of poo poo! Why won't you let me just pipe it straight in!

Jelmylicious
Dec 6, 2007
Buy Dr. Quack's miracle juice! Now with patented H-twenty!

stubblyhead posted:

Sorry to quote from so far back, but good lord you are not kidding about this cmdlet. I have a multi-line comma-delimited string, you stupid piece of poo poo! Why won't you let me just pipe it straight in!

If it is already comma delimited, just pipe it to a text file with .csv as its extension.

stubblyhead
Sep 13, 2007

That is treason, Johnny!

Fun Shoe

Jelmylicious posted:

If it is already comma delimited, just pipe it to a text file with .csv as its extension.

welp guess that would have worked too. :toot: I figured out a lot of poo poo in the process of getting this to work though, so it wasn't a total wash.

adaz
Mar 7, 2009

Jelmylicious posted:

If it is already comma delimited, just pipe it to a text file with .csv as its extension.

This might or might not work depending on the encoding parameters and the parser, I've had issues with it before. IN general I find it easier to use the creating your own object approach.

But yeah, export-csv :negative:

stubblyhead
Sep 13, 2007

That is treason, Johnny!

Fun Shoe

adaz posted:

This might or might not work depending on the encoding parameters and the parser, I've had issues with it before. IN general I find it easier to use the creating your own object approach.

But yeah, export-csv :negative:

Yeah the comments in your code from a few pages back were really helpful. I was using a script one of my colleagues wrote as a template, and he did it in basically the same way. He didn't comment his code though, so I had no idea what he was doing and subsequently left out some pretty important stuff in my own script.

Scaramouche
Mar 26, 2001

SPACE FACE! SPACE FACE!

Hey there 'Shellers (need a better name for PS enthusiasts), for once I'm not coming here with a naked cry for help. Instead this is more of an opinion question. I'm automating some FTP scripts and I'm tired of doing it in batch files so I'm going to PowerShell it. I'm probably going to do this (first answer):
http://stackoverflow.com/questions/1867385/upload-files-with-ftp-using-powershell

But thought I'd check in with you guys to see if there's a cooler way. Right now it's going to be one file (since it's always known and doesn't change) so I don't need to worry about for each or anything like that.

One question I did have, if I needed to extend this to SFTP/FTPS is it actually just as easy as changing the WebRequest.Methods+xxx call?

Nebulis01
Dec 30, 2003
Technical Support Ninny
Stupid question time again, regarding the following script

code:
$Today = (Get-Date -format "yyyy-MM-dd")
$targetFolder = "C:\Backups\FlatFile"
$backupDir = "$targetFolder\$Today"


function Remove-Items
{ 
 $testFolderPath = $targetFolder
 if (Test-Path -Path $testFolderPath)
   { 
     $fiveDaysAgo = (Get-Date).AddDays(-5)        
	#Take ownership of the folders and files in $testFolderPath
	Invoke-Expression "takeown /f $testFolderPath /a /r /d y"
	#Assign the Administrators group Full Control permissions to $testFolderPath
	Invoke-Expression "icacls $testFolderPath /grant administrators:F /t"
	#Delete folders in $targetFolder older than 5 days
	Get-ChildItem -Path $testFolderPath -Recurse | Where-Object { $_.CreationTime -lt $fiveDaysAgo } | Remove-Item -recurse -force
    }
 else 
   {
    Write-Host "$testFolderPath does not exist."
    #Kill Script
    Exit
   }
 }
Remove-Items
It throws receive the following errors

code:
Remove-Item : The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.
At line:1 char:125
+ Get-ChildItem -Path C:\backups\servername\flatfile -Recurse |  where { ((get-date)-$_.creationTime).days -ge 4}  | Remove-Item <<<<  -recurse -force
    + CategoryInfo          : WriteError: (C:\backups\servername\flatfile\2012-04-01:String) [Remove-Item], PathTooLongException
    + FullyQualifiedErrorId : RemoveItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
 
Remove-Item : The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.
At line:1 char:125
+ Get-ChildItem -Path C:\backups\servername\flatfile -Recurse |  where { ((get-date)-$_.creationTime).days -ge 4}  | Remove-Item <<<<  -recurse -force
    + CategoryInfo          : WriteError: (C:\backups\shda...le\2012-04-01\c:String) [Remove-Item], PathTooLongException
    + FullyQualifiedErrorId : RemoveItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
 
Remove-Item : The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.
At line:1 char:125
+ Get-ChildItem -Path C:\backups\servername\flatfile -Recurse |  where { ((get-date)-$_.creationTime).days -ge 4}  | Remove-Item <<<<  -recurse -force
    + CategoryInfo          : WriteError: (C:\backups\shda...ts and Settings:String) [Remove-Item], PathTooLongException
    + FullyQualifiedErrorId : RemoveItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
 
Remove-Item : The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.
At line:1 char:125
+ Get-ChildItem -Path C:\backups\servername\flatfile -Recurse |  where { ((get-date)-$_.creationTime).days -ge 4}  | Remove-Item <<<<  -recurse -force
    + CategoryInfo          : WriteError: (C:\backups\shda...ings\user_ad:String) [Remove-Item], PathTooLongException
    + FullyQualifiedErrorId : RemoveItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
 
Remove-Item : Cannot remove item C:\backups\servername\flatfile\2012-04-01\c\Documents and Settings\user_ad\Local Settings\Temp\hsperfdata_user_ad: Access to the path is denied.
At line:1 char:125
+ Get-ChildItem -Path C:\backups\servername\flatfile -Recurse |  where { ((get-date)-$_.creationTime).days -ge 4}  | Remove-Item <<<<  -recurse -force
    + CategoryInfo          : InvalidArgument: (hsperfdata_user_ad:DirectoryInfo) [Remove-Item], ArgumentException
    + FullyQualifiedErrorId : RemoveFileSystemItemArgumentError,Microsoft.PowerShell.Commands.RemoveItemCommand
Remove-Item : Cannot remove item C:\backups\servername\flatfile\2012-04-01\c\Documents and Settings\user_ad\Local Settings\Temp: The directory is not empty.

At line:1 char:125
+ Get-ChildItem -Path C:\backups\servername\flatfile -Recurse |  where { ((get-date)-$_.creationTime).days -ge 4}  | Remove-Item <<<<  -recurse -force
    + CategoryInfo          : WriteError: (Temp:DirectoryInfo) [Remove-Item], IOException
    + FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
Remove-Item : Cannot remove item C:\backups\servername\flatfile\2012-04-01\c\Documents and Settings\user_ad\Local Settings: The directory is not empty.

At line:1 char:125
+ Get-ChildItem -Path C:\backups\servername\flatfile -Recurse |  where { ((get-date)-$_.creationTime).days -ge 4}  | Remove-Item <<<<  -recurse -force
    + CategoryInfo          : WriteError: (Local Settings:DirectoryInfo) [Remove-Item], IOException
    + FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
Remove-Item : Cannot remove item C:\backups\servername\flatfile\2012-04-01\c\Documents and Settings\user_ad: The directory is not empty.

At line:1 char:125
+ Get-ChildItem -Path C:\backups\servername\flatfile -Recurse |  where { ((get-date)-$_.creationTime).days -ge 4}  | Remove-Item <<<<  -recurse -force
    + CategoryInfo          : WriteError: (C:\backups\shda...ngs\user_ad:DirectoryInfo) [Remove-Item], IOException
    + FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
I tried to end run around Remove-Item by creating the variable $olddata and passing that to the a command prompt invoking RD(rmdir), but that also errors out

code:
$olddata = (Get-ChildItem -Path $testFolderPath -Recurse | where { ((get-date)-$_.creationTime).days -ge 4} | Where {$_.psIsContainer -eq $true} )
    #Remove-Item -Path $olddata -recurse -force 
    Invoke-Expression "rd $olddata /q /s" 
Pass to rd error

code:
Remove-Item : A positional parameter cannot be found that accepts argument 'c'.
At line:1 char:3
+ rd <<<<  2012-04-01 c Documents and Settings user_ad user_ad /q /s
    + CategoryInfo          : InvalidArgument: (:) [Remove-Item], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand
My brain is fried, any idea how I can get Powershell to delete these leftovers?

kampy
Oct 11, 2008

Nebulis01 posted:

Stupid question time again, regarding the following script

It throws receive the following errors

code:
Remove-Item : The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.
At line:1 char:125
+ Get-ChildItem -Path C:\backups\servername\flatfile -Recurse |  where { ((get-date)-$_.creationTime).days -ge 4}  | Remove-Item <<<<  -recurse -force
    + CategoryInfo          : WriteError: (C:\backups\servername\flatfile\2012-04-01:String) [Remove-Item], PathTooLongException
    + FullyQualifiedErrorId : RemoveItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand

Remove-Item : Cannot remove item C:\backups\servername\flatfile\2012-04-01\c\Documents and Settings\user_ad\Local Settings\Temp\hsperfdata_user_ad: Access to the path is denied.
At line:1 char:125
+ Get-ChildItem -Path C:\backups\servername\flatfile -Recurse |  where { ((get-date)-$_.creationTime).days -ge 4}  | Remove-Item <<<<  -recurse -force
    + CategoryInfo          : InvalidArgument: (hsperfdata_user_ad:DirectoryInfo) [Remove-Item], ArgumentException
    + FullyQualifiedErrorId : RemoveFileSystemItemArgumentError,Microsoft.PowerShell.Commands.RemoveItemCommand
Remove-Item : Cannot remove item C:\backups\servername\flatfile\2012-04-01\c\Documents and Settings\user_ad\Local Settings\Temp: The directory is not empty.

At line:1 char:125
+ Get-ChildItem -Path C:\backups\servername\flatfile -Recurse |  where { ((get-date)-$_.creationTime).days -ge 4}  | Remove-Item <<<<  -recurse -force
    + CategoryInfo          : WriteError: (Temp:DirectoryInfo) [Remove-Item], IOException
    + FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
Remove-Item : Cannot remove item C:\backups\servername\flatfile\2012-04-01\c\Documents and Settings\user_ad\Local Settings: The directory is not empty.

Bit of a late reply, but the first error you're running into is the good ole NTFS(?) limitation on path length, which can not exceed ~250 characters. It may also be causing takeown not to work properly which would then account for the two other errors.

You could for example, create temporary file shares in a subdirectory of the path (one at the 2012-04-01 directory in your example case might be good) and do the file removal in those which bypasses the issue.

Quick example of that:
code:
$share = "c:\temp"
# WMI might be a better idea for this but:
invoke-expression ('cmd.exe /c net share hidden$="{0}" /grant:"everyone,full"' -f $share)
pushd \\127.0.0.1\hidden$
rmdir "a path"
popd
invoke-expression ('cmd.exe /c net share hidden$ /delete /y')

Nebulis01 posted:

I tried to end run around Remove-Item by creating the variable $olddata and passing that to the a command prompt invoking RD(rmdir), but that also errors out

code:
$olddata = (Get-ChildItem -Path $testFolderPath -Recurse | where { ((get-date)-$_.creationTime).days -ge 4} | Where {$_.psIsContainer -eq $true} )
    #Remove-Item -Path $olddata -recurse -force 
    Invoke-Expression "rd $olddata /q /s" 
My brain is fried, any idea how I can get Powershell to delete these leftovers?

I believe Invoke-Expression will try to run the powershell version of the command, if it exists, so if you want to run the command prompt version of rmdir, you'd want to do something like this:

code:
# probably a good idea to substitute in the variable names too, this replaces {0} with contents of $olddata:
Invoke-Expression ('cmd.exe /c rd "{0}"' -f $olddata)
Also using foreach to loop through the $olddata variable might be a good idea in this case, since it may return more than one directory.

Honey Im Homme
Sep 3, 2009

I don't suppose anyone has used powershell to bulk migrate user accounts across domains? Ideally keeping all of their properties (profile paths, homedrives etc?)

Is exporting to csv and reimporting on the new domain the best way to do this?

adaz
Mar 7, 2009

Honey Im Homme posted:

I don't suppose anyone has used powershell to bulk migrate user accounts across domains? Ideally keeping all of their properties (profile paths, homedrives etc?)

Is exporting to csv and reimporting on the new domain the best way to do this?

:toot:
I have actually, but not with all the attributes intact, and not in a way that would help you that much. We mirror our AD environment into a SQL db to take the load off the DCs for data queries and the like, so I used SQl to pull in the data. What you would do, conceptually, to pull an entire OU across would be something like this.

code:
# Grab every user on our existing domain domain
 $domain = "LDAP://dc=current,dc=domain"
 $ADSearcher = New-Object System.DirectoryServices.DirectorySearcher $Domain
 $Filter = "(&(objectCategory=Person)(cn=*))"
 $ADSearcher.Filter = $Filter
 $adSearcher.pagesize = 50 # this will pull in 50,000 records. If you need more increase as necessary
 $ADResult = $ADsearcher.FindAll()

# bind to OU in new domain
$newDomain = new-object DirectoryServices.DirectoryEntry("LDAP://ou=users,dc=blah,dc=new,dc=com",username,password)

foreach($user in  $adResult) {
   # Create User
   $newObj = $newDomain.Create("user","CN=$($user.properties["cn"])")
   # Populate properties
   foreach($prop in $user.properties.getEnumerator()) {
     $newObj.put($prop.name,$prop.Value)
  }

 $newObj.setinfo()
}
Couple things I was too lazy to put in there

1.) You can't put in passwords obviously they will be encrypted and hashed. Will need to set a default password.
2.) Various fields (proxy address is a good one) will need to be iterated through and added, they probably won't straight set just by doing a put
3.) Will need to add a filter when going through the properties (Switch would be great for this) to skip adding things like CN, DistinguishedName,badpasswordtime,logoncount,adspath,logontimestamp or any other read only field in AD. You could also filter that out in the Searcher by only returning the things you care about like so

code:
 $domain = "LDAP://dc=current,dc=domain"
 $ADSearcher = New-Object System.DirectoryServices.DirectorySearcher $Domain
 $Filter = "(&(objectCategory=Person)(cn=*))"
 $ADSearcher.Filter = $Filter
# here, which properties we care about instead of "everything"
 $adsearcher.propertiesToLoad.Add("mail")
 $adsearcher.propertiestoload.add("givenname")

 $adSearcher.pagesize = 50 # this will pull in 50,000 records. If you need more increase as necessary
 $ADResult = $ADsearcher.FindAll()

adaz fucked around with this message at 22:52 on Apr 11, 2012

Honey Im Homme
Sep 3, 2009

Thank you so much. Will have a play around and see how things go.

Nebulis01
Dec 30, 2003
Technical Support Ninny

kampy posted:

stuff

Hey thanks for this, i actually just now have a change to look at this script again so good timing. I'll see how it works and report back.

Nebulis01
Dec 30, 2003
Technical Support Ninny

Nebulis01 posted:

Hey thanks for this, i actually just now have a change to look at this script again so good timing. I'll see how it works and report back.

Alrighty, well I ended up not getting it to work the way I wanted. I used ntbackup to create a .bkf of the flatfile stuff that needed to be archived and just had ps move that over, it works out pretty well and deletes when it's supposed to.

NaughtyHusky
Mar 11, 2004
Offical Kristen Bell Stalker
I have a quick question, I am using the following in order to create a last written file output, however I want to format the date in UNIX time (e.g. UFormat %s) - any help or direction would be great. Do I need to go down the object route?

> Get-ChildItem c:\ -recurse | Select-Object FullName, LastWriteTime, length

Jelmylicious
Dec 6, 2007
Buy Dr. Quack's miracle juice! Now with patented H-twenty!

NaughtyHusky posted:

I have a quick question, I am using the following in order to create a last written file output, however I want to format the date in UNIX time (e.g. UFormat %s) - any help or direction would be great. Do I need to go down the object route?

> Get-ChildItem c:\ -recurse | Select-Object FullName, LastWriteTime, length

This should work:

code:
$BeginningOfUnixTime = Get-Date –Date '01/01/1970'
Get-ChildItem c:\ -recurse | Select-Object FullName, @{Name="UNIX Time"; Expression = {($_.LastWriteTime.ToUniversalTime() - $BeginningOfUnixTime).TotalSeconds}}, length
Nicer would be to make a function that converts to unixtime, keep everything more readable:

code:
$BeginningOfUnixTime = Get-Date –Date '01/01/1970'

Function ConvertTo-UNIXtime
    {
    param($Timestamp)
    return ($Timestamp - $BeginningOfUnixTime).TotalSeconds    
    }
    
Get-ChildItem c:\ -recurse | Select-Object FullName, @{Name="UnixTime"; Expression={ConvertTo-UNIXtime $_.LastWriteTime}}, length

adaz
Mar 7, 2009

Here is the function you'll need the question is do you want to make it all pretty with the pipeline input or are you actually exporting this stuff out to CSV or something?

code:
function Get-UnixTime()
{
param($timeToconvert)
$UnixTimeStart = new-object system.datetime(1970, 1, 1, 0, 0, 0, 0)
$span = $timeToconvert - $unixTimeStart.ToLocalTime()
$span.TotalSeconds
}

Powdered Toast Man
Jan 25, 2005

TOAST-A-RIFIC!!!
Just got into PS 2.0 recently and I quickly learned two things:

- Exporting to CSVs is awesome (especially for a major project I'm working on to audit my company's AD forest and control security in the future). By extension, piping in general is awesome for stuff like using the output of one command as the input to another command.

- Get the Quest command suite; everyone uses it anyway (thank you Powershell in Practice).

Also, dunno if anyone else has seen this but the Powershell 2.0 Administrator's Pocket Consultant is available on the Google Play store for only $2.99. It was nice to have a searchable reference always at hand on my phone.

NaughtyHusky
Mar 11, 2004
Offical Kristen Bell Stalker

adaz posted:

Here is the function you'll need

Jelmylicious posted:

This should work

Great stuff, thanks to both of you, and yes I plan to pipe this out to CSV.

Drumstick
Jun 20, 2006
Lord of cacti
Ive run into a small issue. I had to restore network drives from a backup, but ownership and security permissions are not restored. So, now im stuck with 1200 folders that have incorrect ownership and will not be mapped when a user logs in until they have ownership of that folder.
I want to make sure what im thinking makes sense and check to see if there is possibly an easier way to do this.

The folders are their user names. Could I create an array of the names, then use that to assign ownership of the proper folder? Or can I do a for each, read the name then assign that ownership without the array? I'm way to inexperienced at this.

Jelmylicious
Dec 6, 2007
Buy Dr. Quack's miracle juice! Now with patented H-twenty!

Drumstick posted:

The folders are their user names. Could I create an array of the names, then use that to assign ownership of the proper folder? Or can I do a for each, read the name then assign that ownership without the array? I'm way to inexperienced at this.

Yes, Basically you read Foldername, get the user from AD and use Set-ACL to set the new permissions. Be careful not to lock yourself out by overwriting admin permissions. I'll see if I can get you some code.

Drumstick
Jun 20, 2006
Lord of cacti
Fantastic, thank you so much. Im glad i'm at least on the right track. I didnt even consider the possibility of locking myself... Im glad I didnt just wing it.

Jelmylicious
Dec 6, 2007
Buy Dr. Quack's miracle juice! Now with patented H-twenty!

Drumstick posted:

Fantastic, thank you so much. Im glad i'm at least on the right track. I didnt even consider the possibility of locking myself... Im glad I didnt just wing it.

Couldn't fully test, since I am away from my domain right now. This should work. Shouldn't have to tell you, but try it on a testfolder first:

code:
$Location = "e:\Path\to\Profiles"
$Domain = "YourDomainName"
$FolderList = Get-ChildItem $Location
$ACL = Get-ACL $Location #Get Original Permissions of Folder

foreach ($Folder in $FolderList)
    {
    $User = $Domain +"\"+ ($folder.name)  #Make full username as Domani\User
    $permission = $User,"Modify","Allow"  #Permission Rule
    $AccessRule = new-object System.Security.AccessControl.FileSystemAccessRule $permission
    $UserACL = $ACL                       #Reset userACL
    $UserACL.SetAccessRule($AccessRule)   #Modify This ACL with Userpermissions
    set-acl -Path $Folder.FullName -AclObject $UserACL
    }

Drumstick
Jun 20, 2006
Lord of cacti
It works! Thank you so much!

I was wrong. It mostly works. I tired running it on multiple folders and its assigning multiple people to it instead of just the one the folder is named after, and folders/files inside are not inheriting. It looks like some other people in the thread recently had the same issue

Drumstick fucked around with this message at 16:39 on May 2, 2012

adaz
Mar 7, 2009

You need to set inheritance and propagation flags when you create your new access rule. See http://msdn.microsoft.com/en-us/library/ms147785.aspx for the technical writeup but here is a good article explaining it in more general terms: http://camillelemouellic.blog.com/2011/07/22/powershell-security-descriptors-inheritance-and-propagation-flag-possibilities/

So for what you want to do you need to set inheritanceflags of ContainerInherit and ObjectInherit and propogation flags to none.

something like this

code:

$InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [System.Security.AccessControl.InheritanceFlags]::ObjectInherit

$PropagationFlag = [System.Security.AccessControl.PropagationFlags]::None

$objType = [System.Security.AccessControl.AccessControlType]::Allow 

$permission = "domain\user","Modify", $InheritanceFlag, $PropagationFlag, $objType
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission

Adbot
ADBOT LOVES YOU

Drumstick
Jun 20, 2006
Lord of cacti
Fantastic! Thank you everyone for the help. I really appreciate it, and I know my users will too. This is new territory for me and Ive always received great help and advice from these forums.

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