Running ExifTool from MS Access using Visual Basic

Started by brian_mk, December 05, 2017, 12:43:24 PM

Previous topic - Next topic

brian_mk

I have a MS Access database application originally written for 32bit Windows XP and Access 2003.
A while ago, this was moved to another PC running 64bit Windows 10 and Access 2013.

The MS Access app uses some Visual Basic to run ExifTool thus:-

ExecuteCommand (exifTool & " -s " & Chr(34) & ExifFile & Chr(34))

This command fails in the new environment.

I suspect the problem is connected with permissions.
(Note that when I run the MS Access app, it runs as a user that has Admin permissions).

If I try and run ExifTool directly from a DOS Command Window or Power Shell Window thus:-
.\exiftool -ver
It fails (exit code = -1)
If I run the same command in a Power Shell(Admin), then it works as expected.

Any suggestions from MS Access or Visual Basic experts how to make this work?

Cheers,

Brian.






brian_mk

I probably should add that 'exifTool' and 'ExifFile' in the code snippet are strings.
I have used the VB debugger to check that they contain the correct file path to exifTool.exe and to the exif file itself.

Phil Harvey

Hi Brian,

What happens if you right click on exiftool.exe, go to Compatibility, and select "Run this program as administrator"?  (see this post)

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

brian_mk

Hi Phil,

Yes - I tried that. It works ok - I see the help info displayed in a DOS Window.
If I try double clicking without "Run as Administrator", then I get no output.

brian_mk

I should have included the VB function ExecuteCommand().
It looks like this:-

====

Private Function ExecuteCommand(mCommand As String)
        Dim start As STARTUPINFO
        Dim sa As SECURITY_ATTRIBUTES
        If Len(mCommand) = 0 Then Exit Function

        sa.nLength = Len(sa)
        sa.bInheritHandle = 1&
        sa.lpSecurityDescriptor = 0&

        If CreatePipe(hReadPipe, hWritePipe, sa, 0) = 0 Then Exit Function
        start.cb = Len(start)
        start.dwFlags = &H100& Or &H1
        start.hStdOutput = hWritePipe
        start.hStdError = hWritePipe
        If CreateProcessA(0&, mCommand, sa, sa, 1&, &H20&, 0&, 0&, start, proc) <> 1 Then Exit Function

        CloseHandle (hWritePipe)
End Function

====

I suspect this may need tweeking in some way to get admin permission

brian_mk

This information may also be relevant:-

====

Private Declare Function CreatePipe Lib "kernel32" (phReadPipe As Long, phWritePipe As Long, lpPipeAttributes As Any, ByVal nSize As Long) As Long
Public Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, ByVal lpBuffer As String, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As Any) As Long
Private Declare Function CreateProcessA Lib "kernel32" (ByVal lpApplicationName As Long, ByVal lpCommandLine As String, lpProcessAttributes As SECURITY_ATTRIBUTES, lpThreadAttributes As SECURITY_ATTRIBUTES, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As Long, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
Public Declare Function CloseHandle Lib "kernel32" (ByVal hHandle As Long) As Long
Private Type SECURITY_ATTRIBUTES
        nLength As Long
        lpSecurityDescriptor As Long
        bInheritHandle As Long
End Type
Private Type STARTUPINFO
        cb As Long
        lpReserved As Long
        lpDesktop As Long
        lpTitle As Long
        dwX As Long
        dwY As Long
        dwXSize As Long
        dwYSize As Long
        dwXCountChars As Long
        dwYCountChars As Long
        dwFillAttribute As Long
        dwFlags As Long
        wShowWindow As Integer
        cbReserved2 As Integer
        lpReserved2 As Long
        hStdInput As Long
        hStdOutput As Long
        hStdError As Long
End Type
Private Type PROCESS_INFORMATION
        hProcess As Long
        hThread As Long
        dwProcessId As Long
        dwThreadId As Long
End Type
Public hWritePipe As Long
Public hReadPipe As Long
Public proc As PROCESS_INFORMATION

====

"Lib kernel32" looks a bit suspicous now that it's running on a 64bit machine.

Phil Harvey

Sorry, I don't know anything about privileges in VB.  One would think that it should work if exiftool.exe is set to run as admin and the VB program is also run as admin.  But maybe ask this in a VB forum.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

brian_mk

#7
After some more investigation I have discovered that if I right click MS Access and select 'Run as Administrator', then running ExifTool from the VB code works as expected.

However, I don't want to do this every time.
Is there a way to run Access as Administrator by default?

brian_mk

Ok - I think I have a fix.

The most obvious thing to try, under Properties for the Access shortcut, is to choose 'Advanced' under 'Shortcut' tab.
Here there is a 'run as administrator' checkbox.
However, the checkbox is greyed out.

There is another way...
Right click the shortcut for MS Access, choose 'Toubleshoot Compatibility'.
It initially tries Windows 8 compatibility mode, which does not fix the issue.
You then get other options, one of which is to increase privilege and run as admin.
This fixes the problem.

brian_mk

Although I have found a workaround for this issue, I am still puzzled as to why ExifTool needs to be run as admin in the first place.
Why is this the case?
All ExifTool does is read data from a file.


brian_mk

I've now altered the properties for ExifTool itself to always run as admin.
I'm guessing this means it is no longer necessary to run MS Access 2013 as admin, which should be safer.

I still don't understand why ExifTool needs admin permissions just to read a file?
It even needs to be run as admin just to display help or version info.

Phil Harvey

I suspect it needs to run as admin because it executes other files which it has unpacked into the temporary directory.  The ExifTool .exe is a self-extracting archive of perl with the necessary libraries.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).