PowerShell – Query AD for Group Email Addresses…

2014-09-10T22:11:03+00:00 September 10th, 2014|Uncategorized|

Somebody asked me today if there is an easy way to query AD or Exchange for the email addresses of groups.  There most certainly is!  Let’s walk through my train-of-thought here.  First, I started by querying all groups, piped to Format-List, like this…

Get-ADObject -LDAPFilter "(objectclass=group)" -Properties mail|fl

…but in doing so, you get this list of group objects that may or may not have email addresses:

PowerShell Group Email Query

Hmm, we can do better…  Do you want to query ALL groups, or just groups with email addresses?  Well, in our case, we’re really just after groups with email addresses, so I modify my ldap filter accordingly:

Get-ADObject -LDAPFilter "(&(objectclass=group)(mail=*))" -Properties mail|fl

And the results look the same as above, but only the groups we want are listed.  Okay, that’s better.  But of course, if you ONLY want the email addresses, let’s limit the properties in our list:

Get-ADObject -LDAPFilter "(&(objectclass=group)(mail=*))" -Properties mail|fl -Property mail

…and it looks like this:

PowerShell Group Email Query 2

And finally, if you just want the list of email addresses, no attributes; we use the PowerShell equivalent of AWK to split the line…

Get-ADObject -LDAPFilter "(&(objectclass=group)(mail=*))" -Properties mail|fl -Property mail|findstr /v "^$"| %{ $_.Split(' ')[2]; }

And here’s our pretty list:

PowerShell Group Email Query 3

 I hope that helps!

Using Powershell to check password properties…

2017-07-27T00:01:02+00:00 December 5th, 2013|Uncategorized|

Thanks to Mike Driest, who did most of the testing and documentation on this issue…

One of the many benefits of Coretek’s Virtual Clinical Workstation (VCW) solution is the ability to allow users to run their clinical applications through a “thin” client.  A thin client is a small, lightweight computer that contains very little hardware; just the minimum to allow them to connect to more high powered servers on which their applications run.  

Some of these thin clients run a smaller, “lighter” version of  Windows called Windows “Embedded”, while others don’t run Windows at all!  These devices — while being very inexpensive and convenient due to their small footprint (space wise and energy wise) — pose certain technical challenges in a Windows environment.  One such challenge is the ability to change a user’s Active Directory domain password.

We had to do some troubleshooting recently in our lab to determine whether we had the correct settings to allow an Imprivata “service” account to facilitate a domain user password change from a “zero” client – a device that does not run any form of Windows.  As part of our testing, we had to ensure that the test account’s password was expired; to do this in a timely manner, we set the “pwdLastSet” attribute of the test account to ’0′ (zero):

To confirm that the password was indeed expired we used the following PowerShell command (requires the AD DS PowerShell Snap-In)

“Get-ADUser SamAccountName -Properties *”

You’ll see “PasswordExpired: True” and “PasswordLastSet” is blank. 

Before: 

 

After:

 

 I hope you find this tip helpful!

Powershell with embedded VBS…

2017-07-27T00:01:03+00:00 November 21st, 2013|Uncategorized|

I recently have been working on a project where the client uses an application that requires a generic username and password to be passed to the database.  To further complicate the matter the users could not know or input the username/password…

To accommodate the project I started working with the logic and how to accomplish this goal.  I started Imprivata (A Single Sign on Application) and AppSense to launch the app at the end of the userinit process.  Unfortunately, this failed to function due to the outdated server version at the client site.  So I ended up with PowerShell to launch the application…

I wrote 26 lines of code (see below) to check if the script had been run before; if it hadn’t, then it would create a flag.  Once it completed, it would check the flag, run the script, expect Imprivata to proxy the credentials, and the day was saved, right?!? 

 

# Create Windows Shell Object to allow for window to be minimized
$shell = New-Object -ComObject "Shell.Application"
# Create Registry Key Flag if it doesn’t already exist
if (!(test-path -path HKCU:SoftwareCUSTOMER -pathType container))
{
  New-Item -Path HKCU:Software -Name CUSTOMER
  New-ItemProperty "HKCU:SoftwareCUSTOMER" -Name "SynapseLaunched" -Value 0 -PropertyType "DWord"
}
#Check the value of Synapse Launched
if ((Get-ItemProperty 'hkCU:softwareCUSTOMER' -name SynapseLaunched | select -exp SynapseLaunched) -ne 1) 
{ 
  #launch Synapse then minimize all windows
  & 'C:Windowsexplorer.exe' "::{1FBD11EF-1260-11D1-87A7-444553540001}"
  start-sleep -s 2
  $shell.minimizeall() 
  #countdown from 2 seconds to allow app to connect to server
  Start-Sleep -s 2
  #kill Explorer.exe and relaunch
  $proc = Get-Process
  foreach ($objItm in $proc) 
  {
    If ($objItm.ProcessName -eq "explorer") 
    {
       kill $objItm.ID
    }
  }
  #Set SynapseLaunched Dword Value to 1
  Set-ItemProperty 'hkcu:softwareCUSTOMER' -name SynapseLaunched -Value 1  
}  

…Sadly, not so.  Imprivata at the client site was outdated and would not be available to be used for Windows 7 at the site for 2 months, causing an unacceptable delay in the project. 

Well, after the Imprivata approach failed for me, I needed to accomplish what I couldn’t do in Imprivata.  I started by thinking that perhaps I could launch an explorer process (this app is an explorer shell extension) as run as user with my username…  But no dice; the launching of explorer like that didn’t work because it would cause the files I needed to be created in a non-existent user profile, and would error out on the server.

So, I fell back to Windows VBS scripting’s SendKeys.  Since my script was already in PowerShell, and scripting in autoIT or VBS is something I rarely do, I experimented with creating a new Shell object.  Below is the code that I used for that:

 

#proxy Credentials
      $wshell = new-object -com wscript.shell
      $wshell.AppActivate("Windows Security")
      $wshell.sendkeys("{ENTER}")
      start-sleep -m 30
      $wshell.AppActivate("OneSign")
      $wshell.sendkeys("{ENTER}")
      start-sleep -m 30
      $wshell.AppActivate("Windows Security")
      $wshell.sendkeys("USERNAME")
      $wshell.sendkeys("{TAB}")
      $wshell.sendkeys("PASSWORD_OF_USER")
      start-sleep -m 30
      $wshell.sendkeys("{ENTER}") 

By utilizing $wshell = new-object -com wscript.shell, I was able to tap into .Net commands to interact with windows.  Now I could utilize some old VB Scripting code I had laying around from the past…

By utilizing $shell = New-Object -ComObject "Shell.Application", I was able to manipulate the Explorer.exe shell and minimize/maximize windows as I saw fit…

This was a very rewarding exercise.  Through this solution we (Coretek) were able to solve the client’s issues with the app, accommodate both teams (Desktop and PACs), simplify the end user experience, and best of all bring Windows 7 deployments back on schedule!

Send an Email from the Windows Command Prompt or Script, Pt II…

2017-07-27T00:01:03+00:00 November 14th, 2013|Uncategorized|

Following up on the earlier post, “Send an Email from the Windows Command Prompt or Script…

…While I’m somewhat picking up where I left off in Part 1, the situation in that earlier post had special requirements about how the email message had to be sent (controlled source, user interaction, etc.).  But what if you don’t have those requirements?  What if you simply want to send an email from a Windows workstation or Server? 

Well, in that case, simply use PowerShell.  Since version 2, PowerShell has included the Send-MailMessage cmdlet for relatively easy mail sending from almost any modern computer.

Recently, I was telling somebody how do use this method to send messages in a script, and demonstrating the input details such as specifying the SMTP relay server.  The person then asked me, “What if the SMTP server changes?”  Hmm…  Good point.   So I whipped up a few extra lines to work around that problem, and the person thought I should post it here.  Agreed!

Here is the script, put together as plainly as possible, with clearly named variables to help you understand what’s going on:

$MyRecipientEmailAddress = "Fake.Address@CoretekServices.com"
$MySenderEmailAddress = "JPavlov@YourLinuxGuy.com"
$MyRecipient = $MyRecipientEmailAddress.Split("@")
[0] $MyDestinationDomain = $MyRecipientEmailAddress.Split("@")[1] $MyMxRecords = Resolve-DnsName -Type MX -Name $MyDestinationDomain $MyMxRecord = $MyMxRecords[0].NameExchange $MyMessageSubject = "This is a test" $MyMessageBody = "This is the message. Thanks! - Jeremy" Send-MailMessage -To "$MyRecipientEmailAddress" -SmtpServer "$MyMxRecord" -Subject "$MyMessageSubject" -Body "$MyMessageBody" -From "$MySenderEmailAddress"

Remember, the trick is not really the standard options of the cmdlet, but grabbing the possibly-changing MX record for the relay.  This script will dynamically go and get the *current* first-listed MX record for the recipient, and just use that.

And I can almost hear you now, “…But Jeremy, aren’t you side-stepping the built-in fault-tolerance of the MX record?”  Yes, a bit; you can absolutely add a little more code to this and make it aware of the MX ranking, and roll through them and validate until successful.  Maybe I’ll do that in another post…

By the way, while it may not be obvious to you initially, note that I’m just specifying my recipient’s destination SMTP server as my -SmtpServer.  This *should* be fine in many/most cases.  The destination server should be glad to receive and forward the email to the end user that is a part of its own system.  However, some security protection may block this from happening, so be sure to know your destination first.  In my/our case, this was actually being used in an internal system to a friendly destination.  Your result may vary…

Now get out there and send those emails!

How to fix Ownerships and Inheritance on NTFS file systems, Pt. 2…

2017-07-27T00:01:03+00:00 September 18th, 2013|Uncategorized|

For background on this post, make sure to see Part 1, here

Picking up where we left off in Part 1, recall that I had a set of folders that were copied with original source permissions, and as a result, had broken permission “inheritance”.  The copy also brought over the various ownerships, which I was seeking to replace with the local “Administrators” group, according to standard practice of the customer.

So in Part 1, I had written a DOS batch script to loop through the folders and 1.) force down ownership in the new folder sub-structures (in order to follow company standard and be able to seize control of them), and 2.) re-apply inheritance of the administrative permissions from the folders above.  While I’d like to think I accomplished this swimmingly with my batch file, the truth is that it really needs to be in PowerShell in order to satisfy the needs of the team (future-proofing, portability, and such).

Let’s step through the PowerShell version now; but watch carefully because even though it is the same in principle as the DOS batch script in Part 1 (same enough to be worthy of comparison), it actually is a tad different in a few of the steps.

First, we clear the screen, set some variables, and clean up any files from the last run:

clear
$StartDate = date
Write-Host "Setting variables..."
$PARENTDRIVE = "S:"
$PARENTFOLDER = "Apps"
$PARENTPATH = "$PARENTDRIVE$PARENTFOLDER"
$LOCALPATH = "c:temp"
$TAKEOWNLOG = "$LOCALPATHtakeown-FixOwnerships.log"
$ICACLSLOG = "$LOCALPATHicacls-FixInheritance.log"
$ICACLSSUMMARYLOG = "$LOCALPATHicacls-FixInheritance-Summary.log"
Write-Host "Cleaning up log files from previous run..."
del $TAKEOWNLOG
del $ICACLSLOG

Now, with this PowerShell version of the script, I don’t need to write my lists out to a temp file for later processing (like I did with DOS in Part 1); I just dump it all into objects in memory.  Far more efficient!  Like so:

Write-Host "Creating Listing..."
$FolderListing = Get-ChildItem $PARENTPATH

Then, we hit the real work part of the script, where we loop through the folder listing, decend though and fix all the ownerships and inheritance.  This part is actually almost the same as the DOS batch script, actually, except that it’s more… um… awesomer:

Write-Host "Process listing..."
foreach ($FolderItem in $FolderListing)
{
  Write-Host "Fixing ownership: $PARENTPATH$FolderItem"
  Write-Output "Fixing ownership: $PARENTPATH$FolderItem" | Out-File $TAKEOWNLOG -append -encoding Default
  takeown /f $PARENTPATH$FolderItem /R /A /D Y  | Out-File $TAKEOWNLOG -append -encoding Default
  Write-Output "" | Out-File $TAKEOWNLOG -append -encoding Default
  #
  Write-Host "Fixing inheritance: $PARENTPATH$FolderItem"
  Write-Output "" | Out-File $ICACLSLOG -append -encoding Default
  Write-Output "Fixing inheritance: $PARENTPATH$FolderItem" | Out-File $ICACLSLOG -append -encoding Default
  ICACLS $PARENTPATH$FolderItem /inheritance:e | Out-File $ICACLSLOG -append -encoding Default
}

And finally, we create a summary log and create some closing comments before cleaning up:

Write-Host ""
Write-Host "Creating summary log..."
Select-String -pattern "Failed" $ICACLSLOG | Out-File $ICACLSSUMMARYLOG -encoding Default
Write-Host ""
$EndDate = date
Write-Host "Started: $StartDate"
Write-Host "Ended:   $EndDate"
Write-Host ""
Write-Host "...Complete!"

So that’s about it, really.  Note that I’m using the -encoding Default flag  at each Out-File so the file gets written in ANSI (on my system) instead of UniCode.   I don’t know about you, but I can’t stand dealing with UniCode files for text parsing and such.

And in case you prefer it in one contiguous list, here ya go:

clear
$StartDate = date
Write-Host "Setting variables..."
$PARENTDRIVE = "S:"
$PARENTFOLDER = "Apps"
$PARENTPATH = "$PARENTDRIVE$PARENTFOLDER"
$LOCALPATH = "c:temp"
$TAKEOWNLOG = "$LOCALPATHtakeown-FixOwnerships.log"
$ICACLSLOG = "$LOCALPATHicacls-FixInheritance.log"
$ICACLSSUMMARYLOG = "$LOCALPATHicacls-FixInheritance-Summary.log"
Write-Host "Cleaning up log files from previous run..."
del $TAKEOWNLOG
del $ICACLSLOG
Write-Host "Creating Listing..."
$FolderListing = Get-ChildItem $PARENTPATH
Write-Host "Process listing..."
foreach ($FolderItem in $FolderListing)
{
  Write-Host "Fixing ownership: $PARENTPATH$FolderItem"
  Write-Output "Fixing ownership: $PARENTPATH$FolderItem" | Out-File $TAKEOWNLOG -append -encoding Default
  takeown /f $PARENTPATH$FolderItem /R /A /D Y  | Out-File $TAKEOWNLOG -append -encoding Default
  Write-Output "" | Out-File $TAKEOWNLOG -append -encoding Default
  #
  Write-Host "Fixing inheritance: $PARENTPATH$FolderItem"
  Write-Output "" | Out-File $ICACLSLOG -append -encoding Default
  Write-Output "Fixing inheritance: $PARENTPATH$FolderItem" | Out-File $ICACLSLOG -append -encoding Default
  ICACLS $PARENTPATH$FolderItem /inheritance:e | Out-File $ICACLSLOG -append -encoding Default
}
Write-Host ""
Write-Host "Creating summary log..."
Select-String -pattern "Failed" $ICACLSLOG | Out-File $ICACLSSUMMARYLOG -encoding Default
Write-Host ""
$EndDate = date
Write-Host "Started: $StartDate"
Write-Host "Ended:   $EndDate"
Write-Host ""
Write-Host "...Complete!"

Enjoy!

 

 

How to fix Ownerships and Inheritance on NTFS file systems, Pt. 1…

2017-07-27T00:01:03+00:00 August 28th, 2013|Uncategorized|

Following up on Matt’s post last year, and my post about a similar-but-different situation…  I’m just taking Matt’s original notions to the next level, and making the script he described.

It all started after we ran into a situation where someone was migrating some data from one Windows server to another along with the NTFS permissions (using a 3rd-party copy tool).  It was soon discovered that all the permission inheritance was blocked at the point of the copy, and all the ownerships were set to the original owners (not desired in this case).  The company policy dictated that the administrative permissions from the parent folder must flow down, and that all ownerships for files and folders were set to the Administrators group. 

So, I needed to whip up a little script to fix the permission inheritance for all the new subfolders on the destination under one parent folder, and reset the ownerships to the Administrators group for each subfolder as well.

A couple important criteria I had to work around was that I write it so that it only works on the migrated subfolders, so I don’t affect the parent folders under which these new folders were copied (which actually had *intentionally* blocked inheritance and might possibly have intentional alternate owners in some situations).

Well, since all folders ended up in the same destination parent, I naturally wrote a simple little DOS batch script to fix these.  Why DOS batch, you say?  I don’t know, honestly.  Sometimes when I’m thinking through a Linux/Unix scripting situation, I start thinking of it in bash, and change to Perl when I realize it’s too complex.  And similarly in Windows-based environments I start thinking in DOS batch, and then switch to PowerShell when it gets too complex.  Just an old habit that’s hard to break, I guess.

So, walking through the main sections of the script…

First, we do initial setup, set variables for output files and such, and delete the files from the last run of the script (since it would likely be run repeatedly as a maintenance tool):

@ECHO OFF
@cls
1>&2 Echo Setting variables...
SET PARENTDRIVE=S:
SET PARENTFOLDER=Apps
SET PARENTPATH=%PARENTDRIVE%%PARENTFOLDER%
SET LOCALPATH=c:temp
SET FOLDERLIST=FolderList.txt
SET TAKEOWNLOG=takeown-FixOwnerships.log
SET ICACLSLOG=icacls-FixInheritance.log
SET ICACLSSUMMARYLOG=icacls-FixInheritance-Summary.log
1>&2 Echo Cleaning up log files from previous run...
@del %LOCALPATH%%FOLDERLIST%
@del %LOCALPATH%%TAKEOWNLOG%
@del %LOCALPATH%%ICACLSLOG%
@del %LOCALPATH%%ICACLSSUMMARYLOG%

Then, we create a listing file of the top-level folders, and store them in a file (with quotes):

1>&2 Echo Creating Listing...
@FOR /F "tokens=*" %%a in ('"dir %PARENTPATH% /A:D /B"') do @echo "%%a">>%LOCALPATH%%FOLDERLIST%

Now we change to the destination folder, and begin processing.  This is really the meat of the script.  This is where we use takeown to set Adminstrators group ownership to each folder heirarchy, and ICACLS to force permission inheritance (for administrator permissions from the parent):

1>&2 Echo Changing to %PARENTDRIVE% and %PARENTFOLDER%...
%PARENTDRIVE%
CD %PARENTFOLDER%
1>&2 Echo Process listing...
@For /F "tokens=*" %%Q in (%LOCALPATH%%FOLDERLIST%) Do @(
1>&2 Echo Fixing ownership: %%Q
@takeown /f %%Q /R /A /D Y >> %LOCALPATH%%TAKEOWNLOG%
1>&2 Echo Fixing inheritance: %%Q
ECHO Analyzing: %%Q >> %LOCALPATH%%ICACLSLOG%
ICACLS %%Q /inheritance:e /T /C >> %LOCALPATH%%ICACLSLOG%
)

And here is where we wrap it up.  I provide a brief summary report, and say goodbye:

1>&2 Echo Creating summary log...
FindStr /I /C:"failed" /C:"analyzing" %LOCALPATH%%ICACLSLOG% > %LOCALPATH%%ICACLSSUMMARYLOG%
1>&2 Echo ...Complete!

Now here is the whole script again, in once piece:

@ECHO OFF
@cls
1>&2 Echo Setting variables...
SET PARENTDRIVE=S:
SET PARENTFOLDER=Apps
SET PARENTPATH=%PARENTDRIVE%%PARENTFOLDER%
SET LOCALPATH=c:temp
SET FOLDERLIST=FolderList.txt
SET TAKEOWNLOG=takeown-FixOwnerships.log
SET ICACLSLOG=icacls-FixInheritance.log
SET ICACLSSUMMARYLOG=icacls-FixInheritance-Summary.log
1>&2 Echo Cleaning up log files from previous run...
@del %LOCALPATH%%FOLDERLIST%
@del %LOCALPATH%%TAKEOWNLOG%
@del %LOCALPATH%%ICACLSLOG%
@del %LOCALPATH%%ICACLSSUMMARYLOG%
1>&2 Echo Creating Listing...
@FOR /F "tokens=*" %%a in ('"dir %PARENTPATH% /A:D /B"') do @echo "%%a">>%LOCALPATH%%FOLDERLIST%
1>&2 Echo Changing to %PARENTDRIVE% and %PARENTFOLDER%...
%PARENTDRIVE%
CD %PARENTFOLDER%
1>&2 Echo Process listing...
@For /F "tokens=*" %%Q in (%LOCALPATH%%FOLDERLIST%) Do @(
1>&2 Echo Fixing ownership: %%Q
@takeown /f %%Q /R /A /D Y >> %LOCALPATH%%TAKEOWNLOG%
1>&2 Echo Fixing inheritance: %%Q
ECHO Analyzing: %%Q >> %LOCALPATH%%ICACLSLOG%
ICACLS %%Q /inheritance:e /T /C >> %LOCALPATH%%ICACLSLOG%
)
1>&2 Echo Creating summary log...
FindStr /I /C:"failed" /C:"analyzing" %LOCALPATH%%ICACLSLOG% > %LOCALPATH%%ICACLSSUMMARYLOG%
1>&2 Echo ...Complete!

But you know what?  That’s not good enough for Matt and me.  Nope, Matt basically insisted that it had to be done in PowerShell after all.  So of course I did that too, and I’ll put that up next week.  Why PowerShell you say?  I don’t know… Why not?

😉

 

 

PowerShell v4, and Desired State Configuration…

2017-07-27T00:01:03+00:00 August 7th, 2013|Uncategorized|

For me, the most exiting thing to have come out of Microsoft’s TechEd this year is the new PowerShell v4 feature called Desired State Configuration (DSC).  Being able to deploy countless servers, and be assured that they all will have exactly the products you want installed, the way you want them installed, as soon as you want them installed — all with a few lines of scripting code — is priceless.  I know it’s been a couple months now since it was announced, but if you’re anything like me, you’re just really digging in to the Server 2012 R2 features as you get spare time…  and the power of these new features really start to sink in…

If you want to add a server configured like all the rest?  You add a line in an input file.  You want to add a product to hundreds of servers or change a configuration item?  You add a few lines in what is effectively a PowerShell function.  I just can’t help but think how PowerShell has come sooooo far in making a farm of Windows servers as easy as managing a farm of Linux servers has always been the shell and shell tools, or with certain management tools like Puppet and others!  And the Puppet and Chef folks are on board too, as their products start to make best use of these new capabilities.

For all the info you need to get started (if you haven’t already), make sure to check out the TechEd session, “Desired State Configuration in Windows Server 2012 R2 PowerShell”:

…And also catch up on the PowerShell.org blog announcement.  Then, go download the Server 2012 R2 bits and get going!

 😎

 

 

Removing Stuck System Files on Windows 8…

2018-05-06T23:34:08+00:00 July 10th, 2013|Uncategorized|

First off, I want to apologize for the lack of clarity in the title of this post; I honestly couldn’t fit the whole real subject in there.  And even if I could have, it would have been a bit silly anyway.  Here’s what it might have been called:

“Removing system files from a domain-based computer on a hard drive that was previously installed in another computer and your domain is currently un-available…”  Or something like that.  I know it sounds kinda’ crazy, but stick with me here…

Background:

Now, let me explain.  I’m a consultant that rarely goes into our corporate office, and therefore am usually authenticating with a cached domain credential to my laptop.  And as you may know, there are limits to permissions management when a domain is not available.  So when I added a second hard drive from another computer to my Windows 8 laptop, the NTFS permissions put up a pretty good fight in not letting me delete the old SYSTEM files on the now-secondary disk.  in the end, I had to do a handful of steps to seize the permissions on those files and folders before I could delete them, made extra tricky by me being remote to the domain.

How I Got Here:

Here are the steps that got me into the jam in the first place:

– Installed Windows 8 on original LAPTOP1 with a big hard drive as a local user, LAPTOP1Jeremy.Local
– Drove to office, joined to domain as user DOMAINJeremy.Pavlov, went on with life for a while
– Got a new LAPTOP2, and wanted to use big hard drive from LAPTOP1 as secondary disk in LAPTOP2
– Removed big hard disk from LAPTOP1 and installed into LAPTOP2, to what would become E: drive.
– Installed fresh Windows 8 on LAPTOP2 smaller C: drive as a local user, LAPTOP2Jeremy.Local
– Drove to office, joined to domain as user DOMAINJeremy.Pavlov, added DOMAINJeremy.Pavlov as member of local administrators group on LAPTOP2, went on with life
– Wanted to delete system folders (Windows, Program Files, etc.) from big E: drive (forgot to remove them originally), while preserving other folders (Virtual Machines, etc.)

…But, the folder(s) won’t let me delete them so easily.  My user (and Administrator credential) don’t have rights to the tiles, and since I’m not near the office to re-assign domain permission, I need different strategy.  Mind you, I would have just formatted the disk, but I have hundreds of Gigabytes of Virtual Machines on it.  And while I thought about removing the drive, or mounting in Linux, etc., I wanted to find an easier, repeatable way.

Stepping Through It

So, since NTFS won’t let deletion happen as-is, the permissions clearly need to be re-set.  So let’s walk through what we need to do to make this work…

– First, open a command prompt “As Administrator”, and run this command to “Take Ownership” of the unwanted folder on the E: drive:
takeown /f E:Unwanted Folder /R /A
…in this case, the /R means recursive, and the /A means set it to the Administrators group.

– Now that the local Administrators group has control, use the GUI Security tab in Windows Explorer (or PowerShell, or icacls) to grant it FULL CONTROL to This folder, subfolders, and files

– Fix inheritance by checking the box to “Replace all child object permission entries…” on “E:Unwanted Folder”

– Now, remove the unwanted folder with the good ol’ RD command (in the same command window you opened above, or the GUI):
RD /S /Q E:Unwanted Folder
…By the way, I just couldn’t bring myself to put “Windows” above, so I put “Unwanted Folder”.  You get the idea…

Of Course, A Script

Now if you just want to to do the whole thing in a script, here’s how you might do it:

#Set this to the folder to be removed:
SET DELETEME="E:Unwanted Folder"
#Next line sets ownership of hierarchy to Administrators Group
TAKEOWN /f %DELETEME% /R /A
#Next line resets permissions for hierarchy to default
ICACLS %DELETEME% /reset /T
#Next line grants Administrators group "Full Control" to hierarchy 
ICACLS %DELETEME% /grant Administrators:(OI)(CI)F
#Next line removes hierarchy 
RD /S /Q %DELETEME%

…Of course, this is just one way (or two ways) to do it, in one weird situation.  But I thought it could help someone some day…  Maybe even myself…

🙂

PowerShell – How To Discover and Set Permissions on a Folder…

2017-07-27T00:01:03+00:00 June 12th, 2013|Uncategorized|

I’ve written a few posts here in the past about how to use PowerShell to set NTFS permissions, in a couple different fashions.  But recently I was asked something like, “…okay, I know what permissions I’d like to assign in Windows Explorer, but how do I know what the PowerShell equivalent is?” 

The point of the question is that the description of the permission you see in the GUI is not necessarily what you’d actually put in your PowerShell command when you attempt to apply it.  So how do you know the difference and correlation?

There are tons of references out there for learning more about scripting setting permissions in PowerShell, but it’s not always easy to know *which* permission to set with PowerShell.  So let’s imagine the scenario where we need to add a “custom” permission to a folder via a PowerShell script or command (maybe part of a loop, etc.), and the requesting person has only described to you in the most GUI-like terms what is needed. Step1

In this case, what I usually do is:

1.) Ask the person to set the desired permission on an example folder (if it doesn’t exist already) to be sure that you are talking about the same thing, like this example:

…In this example case we are using the following:

Permission 1: Create File / Write Data
Permission 2: Create Folders / Append Data
Permission 3: List Folder / Read Data
At: Folder name “Bogus”
For: This folder, subfolders, and files
To: LABWorkgroup1

 

2.) Use PowerShell command Get-Acl .Bogus | Format-List to get a readable ACL from the example folder:

 Step2

3.) Now, remove that permission from the folder, and run the above command again to see the difference (or just evaluate the SIDs):

Step3

…and now you can see — among the other permissions — that the above listed permissions translate to LABWorkgroup1 Allow  ReadData, CreateFiles, AppendData, Synchronize; and the Sddl, if you need it: (A;OICI;0x100007;;;S-1-5-21-2087276962-282213542-3505124996-1115)

4.) Finally, set the permission on the new folder:

$folder = "Bogus"
$myGroup = "LABWorkgroup1"
$acl = Get-Acl $folder
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$myGroup", "ReadData", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.AddAccessRule($rule)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$myGroup", "CreateFiles", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.AddAccessRule($rule)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$myGroup", "AppendData", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.AddAccessRule($rule)
Set-Acl $folder $acl

This is a simple example, of course, but it’s an easy way to get it done without chasing down reference documentation.  After a while and frequent use, you begin to kinda’ memorize the various PowerShell permissions options and recognize them — but you can sometimes forget them too, and this is a quick and easy way to figure it out at any time.

😎

 

Powershell – Self-Destruct Button…

2017-07-27T00:01:03+00:00 May 29th, 2013|Uncategorized|

While it usually is the case that the owner or creator of a tool or device would like to keep the item he or she has created safe and sound, occasionally one might create a one-time-use tool that is designed to service its purpose for only a brief time, and then be eliminated — in case further use of the tool is harmful to the purpose for which it was originally invented.  Imagine a wrecking ball for instance; while extremely useful during demolition phase, you don’t want it lying about swinging the big iron ball near your new glass windows when construction is nearly completed, do you?

In these cases, I am reminded of Dr. Heinz Doofenshmirtz, the famous inventor.  For those that know me, it will likely come as no surprise that I’m a big fan of the Doctor’s prolific and voluminous work.  One interesting (and perhaps little-known) facet of his work is that each of his inventions holds an essential – but often overlooked – element of self-mitigation.  It has been said that this feature was sometimes erroneously invoked before the completion of its ascribed task, but — and possibly due to the nature of the feature — scant evidence of this is available.  Nonetheless, he was diligent in making sure that the feature was always available, so none of his tools could cause harm beyond its intended usage.

So it is in this vein — and in honor (and in the spirit) of Dr. Doofenshmirtz — that today I’ve written what might perhaps be one of the more intriguing and perhaps jocular scripts yet:  A PowerShell Self-Destruct Button. 

This is a script that prompts you whether or not it should self-destruct; and then if so, promptly deletes itself.  Enjoy:

 

$CurrentScriptFullPathName = $MyInvocation.MyCommand.Definition
$CurrentScriptName = $MyInvocation.MyCommand.Name
clear
write ""
write "Self-Destruct option: "
$SelfDestructChoice = Read-Host "Do you wish for this script ($CurrentScriptName) to destroy itself upon completion? (Enter Yes or No)"
if ("$SelfDestructChoice" -eq "No")
{
  write ""
  write "Okay, this script will not Self-Destruct."
  write "Keeping: $CurrentScriptFullPathName"
  write ""
}
elseif ("$SelfDestructChoice" -eq "Yes")
{
  write ""
  write "You pushed the Self-Destruct button! This script will now attempt to delete itself..." 
  #write ""
  write "Deleting: $CurrentScriptFullPathName"
  Remove-Item $CurrentScriptFullPathName
  Start-Sleep 3
  write ""
  write "Validating removal...  Is $CurrentScriptName still present?"
  Start-Sleep 3
  Test-Path $CurrentScriptFullPathName
  write ""
  Start-Sleep 3
}
else
{
  write ""
  write "Invalid OverRide choice: "$SelfDestructChoice" is not valid.  Must be Yes or No. Exiting!"
  write ""
  exit
}
write "Complete! Exiting..."
Start-Sleep 3

To walk through this script a bit:  During processing, it first gathers up PathName and ScriptName variable values to help it understand where it is and what it might delete (you don’t want to delete the wrong file!).  Then, it asks you the deadly-serious question of whether or not it should be deleted upon completion.  If not, exit.  If so, self-destruct/delete (and validate).  All that, and a few formatting items to make it all nice.

There you go!  You can copy the text into a file, run it, and amaze your friends.  Maybe amaze the entire Tri-State Area!

🙂

 

Load More Posts