MattHiggs

Command line utility to unblock files

17 posts in this topic

#1 ·  Posted (edited)

Wrote a command line utility which will unblock folders and files passed to it as a parameter.  You can pass as many files/folders as you want as a parameter.  If function detects "-r" or "/r" as first parameter, will unblock files recursively for directories that are passed to it.  Will perform following actions:

1) determine version of powershell installed on computer

2) if powershell version is greater than or equal to 3, will use powershell to unblock the files.  Otherwise, will download "streams.exe" for 32-bit systems and "streams64.exe" for 64-bits systems from sysinternals live server and unblock files by deleting the alternate streams on indicated folders.

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseX64=y
#AutoIt3Wrapper_Change2CUI=y
#AutoIt3Wrapper_Res_SaveSource=y
#AutoIt3Wrapper_Res_Language=1033
#AutoIt3Wrapper_Res_requestedExecutionLevel=requireAdministrator
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
; *** Start added by AutoIt3Wrapper ***
#include <InetConstants.au3>
; *** End added by AutoIt3Wrapper ***
; *** Start added by AutoIt3Wrapper ***
#include <AutoItConstants.au3>
#include <WinAPIShPath.au3>
; *** End added by AutoIt3Wrapper ***
#cs ----------------------------------------------------------------------------

    AutoIt Version: 3.3.15.0 (Beta)
    Author:         myName

    Script Function:
    Template AutoIt script.

#ce ----------------------------------------------------------------------------

; Script Start - Add your code below here
#include <Array.au3>
#include <File.au3>
#include <WinAPIFiles.au3>
Opt("ExpandEnvStrings", 1)
$aCmdLine = _WinAPI_CommandLineToArgv($CmdLineRaw)
$recurs = False
If $aCmdLine[1] = "/?" And Int($aCmdLine[0]) = 1 Then
    ConsoleWrite(@CRLF & @CRLF & @TAB & @TAB & @TAB & @TAB & @TAB & "Unblock Files Command Line Utility" & @CRLF & @CRLF & "Unblock files." & @CRLF & "new_unblock.exe [/r] [[[drive:][path][filename]0] .... [[drive:][path][filename]n]]" & _
            @CRLF & @CRLF & "/r" & @TAB & "if any of the paths that are passed to the tool are directories, this switch will recursively unblock all files within the directory." & _
            @CRLF & @CRLF & "[[[drive:][path][filename]0] .... [[drive:][path][filename]n]]" & @TAB & "The paths that are passed to the tool to be unblocked.  These paths can be files or folders.  If a folder is specified, only the files in the root of that directory will be unblocked unless the /r switch is specified." & @CRLF)
ElseIf $aCmdLine[1] = "/?" And Int($aCmdLine[0]) > 1 Then
    ConsoleWriteError('Unexpected number of arguments.  For information on how to use this tool, run "new_unblock.exe /?".' & @CRLF)
Else
    For $i = 1 To $aCmdLine[0] Step 1
        If ($aCmdLine[$i] = "/r" Or $aCmdLine[$i] = "-r") And $i = 1 Then
            $recurs = True
            ContinueLoop
        EndIf
        If IsFile($aCmdLine[$i]) = 0 Then
            If $recurs = True Then
                $files = _FileListToArrayRec($aCmdLine[$i], "*", $FLTAR_FILES, $FLTAR_RECUR)
            Else
                $files = _FileListToArray($aCmdLine[$i], "*", $FLTA_FILES)
            EndIf
            For $b = 1 To $files[0] Step 1
                If FileExists($aCmdLine[$i] & "\" & $files[$b] & ":Zone.Identifier") Then
                    ConsoleWrite ( "Unblocking file " & $aCmdLine[$i] & "\" & $files[$b] & @CRLF )
                    _WinAPI_DeleteFile($aCmdLine[$i] & "\" & $files[$b] & ":Zone.Identifier:$DATA")
                Else
                    ContinueLoop
                EndIf
            Next
        Else
            If FileExists($aCmdLine[$i] & ":Zone.Identifier") Then
                ConsoleWrite ( "Unblocking file " & $aCmdLine[$i] & @CRLF )
                _WinAPI_DeleteFile($aCmdLine[$i] & ":Zone.Identifier:$DATA")
            Else
                ContinueLoop
            EndIf
        EndIf
    Next
    ConsoleWrite ( "DONE" & @CRLF )
EndIf



Func IsFile($sFilePath)
    Return Number(FileExists($sFilePath) And StringInStr(FileGetAttrib($sFilePath), "D", 2, 1) = 0)
EndFunc   ;==>IsFile

*Edit 2/3/2017: I updated the code so that, when the powershell method is used, a path that is under "Program files" or "program files (x86)" does not return an error.

**EDIT: The script has been re-written so that it is able to accomplish the same functionality without any prerequisites.  Only runs pure AutoIT now.  A big thanks to @argumentum for the idea.

Edited by MattHiggs
1 person likes this

Share this post


Link to post
Share on other sites



#2 ·  Posted

**Updated.  Now allows users to successfully pass environment variables as part of the path specified in the arguments.  Also made some changes to improve performance.

Share this post


Link to post
Share on other sites

#3 ·  Posted

What exactly do you mean by unblock? 

Does this take ownership of files and allow you to delete them when owned by another user or does this literally remove locks on files when held by another process, such as when scite has a lock on the parent folder of the open script and does nto allow you to delete it until the process is closed

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

7 hours ago, Chance said:

What exactly do you mean by unblock? 

Does this take ownership of files and allow you to delete them when owned by another user or does this literally remove locks on files when held by another process, such as when scite has a lock on the parent folder of the open script and does nto allow you to delete it until the process is closed

Hello Sir.  No.  This script will allow you to eliminate occurrences like these:

unblock.jpg

When this property is set on a file (usually when a file is downloaded from the internet), you will encounter the following when trying to run it:

113486d1289590705-open-file-security-war

For example, say you download a powershell  script from Microsoft's  script repository (let say this one for example.)  When you download it, you can verify by right clicking the file, selecting properties, and looking at the security attribute that the file is blocked.  If you try to utilize this script (the example has to be "dot sourced" first, which basically means you type in ". Path\to\script\script.ps1" into powershell console) without first unblocking the file, the below prompt will appear every time:

dVDTrgY.png

Which, if you are trying to automate a process, will kind of get in the way of that.  The script I have provided will remove the blocked status from the files which are passed to it in the command line, thus removing the extra prompt that appears before executing.

Edited by MattHiggs

Share this post


Link to post
Share on other sites

#5 ·  Posted

There's a PS cmdlet that does the same thing without having to download anything, use Unblock-File -Path <filepath\filename>


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

1 hour ago, BrewManNH said:

There's a PS cmdlet that does the same thing without having to download anything, use Unblock-File -Path <filepath\filename>

You should take a look at the description/script source....:mellow::mellow::mellow:

Edited by MattHiggs

Share this post


Link to post
Share on other sites

#7 ·  Posted

My bad, didn't read far enough into the script.


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

#8 ·  Posted

8 hours ago, BrewManNH said:

My bad, didn't read far enough into the script.

No worries dude...  I would be lying if I said I wasn't guilty of the same, lol.

Share this post


Link to post
Share on other sites

#9 ·  Posted

oh snap, I see now. This is useful when you download a project and keep getting that dumb untrusted warning.

 

Thanks

Share this post


Link to post
Share on other sites

#10 ·  Posted

10 hours ago, Chance said:

oh snap, I see now. This is useful when you download a project and keep getting that dumb untrusted warning.

 

Thanks

Exactly..

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

why not just:

If FileExists($sFile & ":Zone.Identifier") Then
    FileClose(FileOpen($sFile & ":Zone.Identifier", 2))
    FileWrite($sFile & ":Zone.Identifier", "[ZoneTransfer]" & @CRLF & "ZoneId=0" & @CRLF) ; ZoneId=5 would work too
EndIf

not as clean but it'd solve the problem without the prerequisites. 

Thanks for sharing @MattHiggs 

 

Edit: Found a way to delete the stream

#include <WinAPIFiles.au3>
If FileExists($sFile & ":Zone.Identifier") Then
    _WinAPI_DeleteFile($sFile & ":Zone.Identifier:$DATA") ; this will remove the stream
EndIf

:)

Edited by argumentum

Share this post


Link to post
Share on other sites

#12 ·  Posted

17 hours ago, argumentum said:

why not just:

If FileExists($sFile & ":Zone.Identifier") Then
    FileClose(FileOpen($sFile & ":Zone.Identifier", 2))
    FileWrite($sFile & ":Zone.Identifier", "[ZoneTransfer]" & @CRLF & "ZoneId=0" & @CRLF) ; ZoneId=5 would work too
EndIf

not as clean but it'd solve the problem without the prerequisites. 

Thanks for sharing @MattHiggs 

 

Edit: Found a way to delete the stream

#include <WinAPIFiles.au3>
If FileExists($sFile & ":Zone.Identifier") Then
    _WinAPI_DeleteFile($sFile & ":Zone.Identifier:$DATA") ; this will remove the stream
EndIf

:)

Because I'm not as smart/knowledgeable as you veteran scripters, lol.

Share this post


Link to post
Share on other sites

#13 ·  Posted

19 hours ago, argumentum said:

why not just:

If FileExists($sFile & ":Zone.Identifier") Then
    FileClose(FileOpen($sFile & ":Zone.Identifier", 2))
    FileWrite($sFile & ":Zone.Identifier", "[ZoneTransfer]" & @CRLF & "ZoneId=0" & @CRLF) ; ZoneId=5 would work too
EndIf

not as clean but it'd solve the problem without the prerequisites. 

Thanks for sharing @MattHiggs 

 

Edit: Found a way to delete the stream

#include <WinAPIFiles.au3>
If FileExists($sFile & ":Zone.Identifier") Then
    _WinAPI_DeleteFile($sFile & ":Zone.Identifier:$DATA") ; this will remove the stream
EndIf

:)

But the script would be better if it didn't have any prerequisites or dependencies, so I updated the script with the code you provided.  You know it's funny, before I began work on this script, I remember doing research in order to determine how Windows flagged a file as "blocked" in order to be able to accomplish what you just showed me, but came up nil after about 30 minutes so I gave up and settled on using the prerequisite methods.  The script in the main post has been updated.

1 person likes this

Share this post


Link to post
Share on other sites

#14 ·  Posted

you can always rewrite _WINAPI_DeleteFIle, extracting only what u need. Basically, that example is just deleting the NTFS Alt Stream.


What is what? What is what.

Share this post


Link to post
Share on other sites

#15 ·  Posted

6 hours ago, Biatu said:

you can always rewrite _WINAPI_DeleteFIle, extracting only what u need. Basically, that example is just deleting the NTFS Alt Stream.

I am not sure what you mean....:mellow::mellow:  I was under the impression that the NTFS Alt Stream is the "flag" which indicates that a file came from the internet and is what "blocks" the file.  Therefore, deleting the Alt Stream would unblock the file, which is the goal.  Can you be a bit more detailed in what you mean?  Examples?

Share this post


Link to post
Share on other sites

#16 ·  Posted

Well, you mentioned that you'd prefer not to have any includes. So, just rewrite the function and pull what is needed from _WinAPI_DeleteFile . Ya know?

And as for Alt Streams...you can store anything in those. Back in the day viruses could be hidden in them, and could be executed directly.


What is what? What is what.

Share this post


Link to post
Share on other sites

#17 ·  Posted

20 hours ago, Biatu said:

Well, you mentioned that you'd prefer not to have any includes. So, just rewrite the function and pull what is needed from _WinAPI_DeleteFile . Ya know?

And as for Alt Streams...you can store anything in those. Back in the day viruses could be hidden in them, and could be executed directly.

Im sorry man.  The more you say the more confused I get.  What I was probably referring to in regards to not wanting to have any includes is the fact that the first version of this script used powershell if the version was high enough to contain the "Unblock-file" cmdlet, and if it wasn't, the script would download and use the streams sysinternals tool to delete the alternate streams instead.  However, I have since completely re-written the script so that it no longer requires these external dependencies.  As in the script can be run completely standalone.  That was the goal, and that has been accomplished.  At this point, my interest in continuing to work on it is non-existent, but you are free to do with it as you like.:P

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now