zim-desktop-wiki / zim-desktop-wiki

Main repository of the zim desktop wiki project
http://zim-wiki.org
GNU General Public License v2.0
1.89k stars 368 forks source link

Plugin can't execute bat file command under Windows OS with error "The system cannot find the file specified" #2261

Open mquan86 opened 1 year ago

mquan86 commented 1 year ago

Describe the bug When insert UML diagram, it will fail to generate image with error "The system cannot find the file specified" It is because Python has a problem to detect the command file with .bat extension

I believe it is this part in applications.py: https://github.com/zim-desktop-wiki/zim-desktop-wiki/blob/2d2970fc136eb6baf00d62e8d7ad1e024e54dcab/zim/applications.py#L294-L309

Should add shell = True to compatible for Windows? Reference of similar issue in another repo: https://github.com/mikitex70/plantuml-markdown/issues/11

To Reproduce

  1. Windows OS, installed PlantUML, install PlantUML plugin (https://gitlab.com/Voyvode/zim-umldiagrameditor)
  2. Has plantuml.bat in Zim application folder (so the plugin can call plantuml command)
  3. In Zim, Insert an UML
  4. Error "The system cannot find the file specified"

Logs:

INFO: Running: ('plantuml', 'C:\\Zim\\tmp\\zim-zizy_qsp\\umldiagram.png', 'C:\\Zim\\tmp\\zim-zizy_qsp\\umldiagram.puml') (cwd: None)
DEBUG: Running ErrorDialog
DEBUG: The system cannot find the file specified

Expected behavior Should no error and able to execute command of bat file.

Screenshots image

Environment (please complete the following information):

Toggoren commented 1 year ago

How to fix:

Easy path:

  1. remove .bat
  2. install plantuml via Chocolatey

Not easy path:

  1. remove .bat
  2. install AutoIt
  3. compile this script
    
    #include <AutoItConstants.au3>
    #include <MsgBoxConstants.au3>

RunPlantUML()

Func RunPlantUML() Local $iPID = Run(@comspec & StringFormat(" /C java -jar ""%s"" %s", "!!!PUT THERE FULL PATH TO plantuml.jar!!!", $CmdLineRaw), "", @SW_HIDE, BitOR($STDERR_CHILD, $STDOUT_CHILD)) ProcessWaitClose($iPID)

Local $sOutput = "" While 1 $sOutput &= StdoutRead($iPID) If @error Then ExitLoop EndIf MsgBox($MB_SYSTEMMODAL, "Stdout Read:", $sOutput) WEnd

$sOutput = '' While 1 $sOutput &= StderrRead($iPID) If @error Then ExitLoop EndIf MsgBox($MB_SYSTEMMODAL, "Stderr Read:", $sOutput) WEnd EndFunc ;==>RunPlantUML


4. add resulting executable to PATH system variable
5. if it didn't work (even after restarting the computer), then go back to "Easy path:"

Current situation: 
``umldiagrameditor: dotcmd = ('plantuml')`` passes through  
``Zim Desktop Wiki: Application.run``  
``Python: subprocess.Popen``  
``WinAPI: CreateProcessW``  
and pushed into ``lpCommandLine``  
Then, according to the documentation ([`` If the file name does not contain an extension, .exe is appended``](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa)),
a ``.exe`` is added to it

My thoughts:
1. In theory, the plugin should itself look for the executable file it needs, because it is impossible to know which of the existing executable files it needs to work.
You can use ``shutil.which`` to search.
2. By the way, it is possible to replace ``Application._lookup`` with ``shutil.which`` almost completely except for the part with ``_CAN_CALL_FLATPAK_HOST_COMMAND``
mquan86 commented 1 year ago

@Toggoren I actually prefer a solution that doesn't depend on third party one like chocolatey or autoit, as I prefer a portable thing. Also fix that may fix many similar issues as well not just PlantUML in my particular case. I also notice that in tryexec(), they support scan with extension, then there should be no reason not to fix the run() to execute it properly.

in tryexec/_lookup function: https://github.com/zim-desktop-wiki/zim-desktop-wiki/blob/2d2970fc136eb6baf00d62e8d7ad1e024e54dcab/zim/applications.py#L217-L226

A note about the workaround above, I didn't test it yet, but I think it may most likely doesn't work strange away if there is executable in PATH environment. The reason is either Python or Zim doesn't actually work well with the PATH in Windows for some reason. Usually, I have to put the thing into Zim folder to make it works. I have a serval case like that already.

About the workaround, it is actually simple that I can just modify the plugin python file to call run with argument plantuml.bat instead of plantuml.

        # Call PlantUML
        try:
            #dot = Application(dotcmd)
            dot = Application('plantuml.bat')