Yubico Forum
https://forum.yubico.com/

[SOLVED] Sharing Violation with GPG2.1 and Windows 7
https://forum.yubico.com/viewtopic.php?f=26&t=1858
Page 1 of 1

Author:  mfaine [ Mon Apr 27, 2015 6:47 pm ]
Post subject:  [SOLVED] Sharing Violation with GPG2.1 and Windows 7

I have been fighting a battle with a sharing violation for about 3 days now and I finally solved the problem so I thought I'd document my solution here in case it is in any way helpful to others.

I'm using GPG2.1 on Windows 7 with two other card readers in addition to the Yubikey Neo. After a lot of searching the common consensus was that this is caused by another program blocking scdaemon's access. But which one? Through the process of elimination I found that, at least for me, the process is the service "Certificate Propagation Service".

I cobbled together a script from snippets I found online and set it to run (with highest privileges) on login using Task Scheduler. It still isn't perfect, for example, I'd like for it to mount my flash drive if it's not already mounted, but I haven't figured out how to do that yet. However, it will wait until I get around to doing it manually. My GPG keyring is on a bitlocker encrypted flash drive, so it's important that it wait until the drive is accessible. You may not need this part so you can of course modify it to suit your needs. I'm sure there are different ways to accomplish this and most likely even better ways, and I'd appreciate any improvements, but it works for me as is, at least well enough.

The script basically just stop the problem service, restarts the smart card service, runs gpg --card-status, then starts the certificate propagation service up again.

Sources:
http://www.motobit.com/tips/detpg_vbs-w ... t-service/
http://www.tek-tips.com/viewthread.cfm?qid=1619385
viewtopic.php?f=26&t=1718
* Some others I don't remember

Code:
Set fso = CreateObject("Scripting.FileSystemObject")
Set WshShell = CreateObject("WScript.Shell" )

' Make sure that the USB flash drive containing my GnuPG keyring is mounted.
' It's encrypted so we need to wait, since we don't want to do anything else until it is mounted.
Do
If fso.FolderExists("D:\private\gpg") Then
   'safe to continue
   Exit Do
Else
   WScript.Sleep 10000
End If
Loop

StopService ".", "CertPropSvc", True
RestartServices ".", "SCardSvr"
gpgagent = Quotes("C:\Program Files (x86)\GnuPG\bin\gpg.exe") & _
" --card-status "
WshShell.Run gpgagent, 0
' Give it a chance to start the daemon and read from the smart card
WScript.Sleep 10000
StartService ".", "CertPropSvc", True
Set WshShell = Nothing

Sub RestartServices(Computer, ServiceNames)
  Dim ServiceName, Counter, aServiceNames

  'Get the array of service names 
  aServiceNames = split(ServiceNames,",")
 
  'loop services from beginning, stop them
  For Each ServiceName In aServiceNames
    StopService Computer, ServiceName, True
  Next

  'loop services from end, start them
  For Counter = ubound(aServiceNames) To 0 Step -1
    StartService Computer, aServiceNames(Counter), True
  Next
End Sub

Function Quotes(ByVal strValue)
    Quotes = Chr(34) & strValue & Chr(34)
End Function

Sub StopService(Computer, ServiceName, Wait)
  Dim cimv2, oService, Result

  'Get the WMI administration object   
  Set cimv2 = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _ 
  Computer & "\root\cimv2")

  'Get the service object
  Set oService = cimv2.Get("Win32_Service.Name='" & ServiceName & "'")
 
  'Check base properties
  If Not oService.Started Then
    ' the service is Not started
    'wscript.echo "The service " & ServiceName & " is Not started"
    exit Sub
  End If

  If Not oService.AcceptStop Then
    ' the service does Not accept stop command
    'wscript.echo "The service " & ServiceName & " does Not accept stop command"
    exit Sub
  End If
 
  'wscript.echo oService.getobjecttext_

  'Stop the service
  Result  = oService.StopService
  If 0 <> Result Then
    'wscript.echo "Stop " & ServiceName & " error: " & Result
    exit Sub
  End If
 
  Do While oService.Started And Wait
    'get the current service state
    Set oService = cimv2.Get("Win32_Service.Name='" & ServiceName & "'")
    'wscript.echo now, "StopService", ServiceName, oService.Started, _
   'oService.State, oService.Status
    Wscript.Sleep 200
  Loop   
End Sub


Sub StartService(Computer, ServiceName, Wait)
  Dim cimv2, oService, Result

  'Get the WMI administration object   
  Set cimv2 = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
  Computer & "\root\cimv2")

  'Get the service object
  Set oService = cimv2.Get("Win32_Service.Name='" & ServiceName & "'")
   
  'Path = "winmgmts:{impersonationLevel=impersonate}!\\" & Computer & _
  '  "\root\cimv2:Win32_Service.Name='" & ServiceName & "'"

  'Get the WMI administration object of the service   
  'Set oService = GetObject(Path)

  'Check base properties
  If oService.Started Then
    ' the service is Not started
    'wscript.echo "The service " & ServiceName & " is started."
    exit Sub
  End If
 
  'Start the service
  Result = oService.StartService
  If 0 <> Result Then
    'wscript.echo "Start " & ServiceName & " error:" & Result
    exit Sub
  End If
 
  Do While InStr(1,oService.State,"running",1) = 0 And Wait
    'get the current service state
    Set oService = cimv2.Get("Win32_Service.Name='" & ServiceName & "'")
    'wscript.echo now, "StartService", ServiceName, oService.Started, _
   'oService.State, oService.Status
    Wscript.Sleep 200
  Loop   
End Sub


I hope this saves someone a little time and stress.

Page 1 of 1 All times are UTC + 1 hour
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/