PowerShell script to get AD-Pictures works inside PowerShell, but not directly from PowerShell.exe -Command

Answered PowerShell script to get AD-Pictures works inside PowerShell, but not directly from PowerShell.exe -Command

  • Thursday, December 06, 2012 10:02 PM
     
     

    I have tried lots of parsing, doublequoting, Backquote escaping, etc. But I cannot get this to work.

    What works:

    1> PowerShell.exe
    2> ([ADSISEARCHER]"samaccountname=$env:username").findone().properties.thumbnailphoto | set-content d:\$env:username.jpg -Encoding byte

    (It will perform an AD-Search for the currently logged on user's thumbnailpicture and then write that to a file)

    What doesn't work:

    1> PowerShell.exe "([ADSISEARCHER]"samaccountname=$env:username").findone().properties.thumbnailphoto | set-content d:\$env:username.jpg -Encoding byte"

    I have tried a simpler example and that DID work: powershell.exe "[ADSISEARCHER]""samaccountname=$env:username""" but I don't understand why that doublequoting works. As soon as I try to change it to powershell.exe "([ADSISEARCHER]""samaccountname=$env:username"")" it stops working

    I did a very simple test and this actually DOES work: powershell "write-host("$env:username") | format-table"

    I am writing a big script that sometimes needs some powershell oneliners. Putting these in .ps1 files and executing them is not possible because of security restrictions. Can anyone help me getting this onliner to work?

All Replies

  • Thursday, December 06, 2012 10:16 PM
    Moderator
     
     
    Have you considered encoding your script as Base64 and passing that to powershell.exe using -EncodedCommand?

    [string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "

  • Thursday, December 06, 2012 10:39 PM
    Moderator
     
     

    The issue you are having is that you're trying to pass specially-quoted strings to PowerShell on the executable's command line.

    You say you're writing a big script that uses one-liners. What language is this script written in? Can you give an example of how you're trying to call one of these one-liners?

    Bill

  • Friday, December 07, 2012 9:31 AM
     
     

    My script is written entirely in Batch and is used to roll-out Windows 8 on our client computers. There is a requirement not to change any security settings from Windows defaults and not to use any other tools that are not built into Windows 8 (staying as pure as possible is the mantra).

    A very much shortened and simplified example of my script would look like this:

    @echo off
    setlocal
    cd /d "%~dp0"
    mode 150

    :GetDataDriveLetter
    rem Parsing the output of a diskpart query to search for a given label and saving the found drive for further use
    set datadrivelabel=data
    for /f "tokens=3" %%a in ('echo list vol ^| diskpart ^| findstr /i %datadrivelabel%') do set datadrive=%%a
    echo datadrive="%datadrive%"
    if defined datadrive (goto :SaveProfilePictureToDataDrive) else (echo couldn't find a datadrive & goto exit)

    :SaveProfilePictureToDataDrive
    echo now trying to save the picture
    rem A working test command for Powershell that contains Braces, Quotes, Variables and Piping
    PowerShell.exe "write-host("$env:username") | format-table"
    rem the non-working command that does work if it is executed directly inside powershell
    rem currently the d:\ path is hardcoded but that should become %datadrive%:\%username%\ in the future
    PowerShell.exe "([ADSISEARCHER]"samaccountname=$env:username").findone().properties.thumbnailphoto | set-content d:\$env:username.jpg -Encoding byte"

    :exit
    if "%1" EQU "" pause
    endlocal


    AvG

  • Friday, December 07, 2012 9:36 AM
     
     

    I haven't looked into that. I have checked the -File and -Command options and they seemed to be able to do what I want. If possible I would like to avoid encoding because it would make the script unreadable and less maintainable. If my command would be very complicated I would understand that encoding is needed, but the two test that I have done seem to indicate that everything I want is possible:

    Test 1:
    powershell "write-host("$env:username") | format-table"
    proves that Braces, Quotes, Variables and Piping are all working without any problem

    Test 2:
    powershell.exe "[ADSISEARCHER]""samaccountname=$env:username"""
    proves that the square brackets are also not a problem


    AvG

  • Friday, December 07, 2012 3:29 PM
    Moderator
     
      Has Code

    You don't have to change any security settings from their defaults on Windows. You can simply bypass the PowerShell execution policy by calling:

    powershell.exe -ExecutionPolicy Bypass -File "%~dp0MyScriptFile.ps1"

    Easy!


    If this post was helpful, please click the little "Vote as Helpful" button :)

    Trevor Sullivan
    Trevor Sullivan's Tech Room
    Twitter Profile

  • Friday, December 07, 2012 3:41 PM
     
     

    If Windows 8 is set up and joined to a doamin then the users AD picture will be what shows.  There is no need to copy it locally. Windows does that automatically for all versions of Windows since XP as far as I know.  Just store the users pictures in AD and it will be the default profile picture for a domain login.

    In Windows 8 the same is true for a Microsoft account (hotmail or msn).  When choosing to use one of these the picture associated with that account will be what is displayed. This will be the display on Windows 8 TR, Windows 8, Windows 8 Pro and all versions of Windows Mobile.  Just use an associated account.

    From your request I suspect you are doing something odd in the installation setup.  Is this for a  school class or other training? 

    The Windows Deployment forum would be more useful for learning how to best automate a deployment.  The MDT has all ot the tools needed to fully deploy most versions of Windows with very little pain. Mostly you will just use the GUIeditor to specfiy the system settings you want in the deployment.  In rare instances you can attach a script to the deployment package.  Profile pictures are outside of the deployment realm.

    I believe if you follow through on this suggestion that you will find there is an easier and more powerful way to deploy WIndows.


    ¯\_(ツ)_/¯

  • Friday, December 07, 2012 4:01 PM
     
     Answered

    Here is how to get out of the problem of strings and things on a command line:

    The following needs to be all on one line

    powershell -command
        "
             (ADSISEARCHER]$('samaccountname='+$($env:username))).findone()
             .properties.thumbnailphoto |
             set-content c:\$env:username.jpg -Encoding byte
        "

    Note it is all in quotes but inner strings are in single quotes.


    ¯\_(ツ)_/¯

  • Monday, December 10, 2012 8:37 AM
     
     
    I am doing a very custom install for the company I work in. Of course I am using some tools from the MDT for that but scripting is absolutely needed to get things done the way we want it without much manual work afterwards. It is not my experience that the windows account picture is set automatically when you join a domain. Tools like Outlook, Lync and SharePoint are all correctly setup to do this already but Windows needs manual work for this

    AvG

  • Monday, December 10, 2012 8:40 AM
     
     

    Thanks, I had tried using the single quotes and the backquotes but didn't know about the use of the $. There was 1 tiny error in your code where it missed the opening square bracket so just for future reference this is the final code:

    powershell -command "([ADSISEARCHER]$('samaccountname='+$($env:username))).findone().properties.thumbnailphoto | set-content d:\$env:username.jpg -Encoding byte"


    AvG

  • Monday, December 10, 2012 4:46 PM
     
     

    Sorry about the brace missing.  I edited teh code after I pasted it becuse I lost the leading '(*' but didn't see that the edit overwrote the first brace.

    There are NO backquotes. There are single quotes.

    Normally we could write this:

    ([ADSISEARCHER]"samaccountname=$env:username").findone()

    This would be the shortest method of expressing the call. The doubleqwuotes wqoul evaluate teo the correct form.

    IN a command line we have to hide everything that we want passed to the PowerShell instance from being evaluated by the currentcommand processor.

    "([ADSISEARCHER]'samaccountname='+$($env:username)).findone()"

    This forces the whole string to be passed and does not alter the contents.

    This also works at a CMD prompt but not at a PowerShell prompt:
    powershell -command "([ADSISEARCHER]('samaccountname='+$env:username)).findone()"

    In this case we encapsulated in () to force evaluation.

    From PowerShell we can do it like this:

    powershell -command {([ADSISEARCHER]$('samaccountname='+$env:username)).findone()}

    Same string but replace quotes with braces.

    All of the above are on one line but may wrap in browser.


    ¯\_(ツ)_/¯