Jump to content

Issues running a DOS copy command


bdg2814
 Share

Recommended Posts

I am having problems running the DOS copy command from within a script. Ultimately, I want to combine the cotents of files A and B into file C.  This snippet only shows one file being copied which could be done with the filecopy function.  Since I have to combine two different files into one I thought I could use the DOS copy command with the following syntax

copy "A"+"B" "C"

I could not get that to work with the run command, runwait, shellexecute etc. so I simplifed the command to get the to work with only one file figuring that I could add the second file once the syntax was correct.

Code as follows

$cmd = @ComSpec & ' /c copy ' & '"' & $Tmp_EmpFileFullFN & '" "' & $EmpFileFullFN & '"'
$RStat = Run($cmd, "",  @SW_MAXIMIZE)

ConsoleWrite($cmd & " (" & $RStat & ") (" & @error & ")")

Output from the consolewrite command

C:WINDOWScmd.exe /c copy "C:tempemployeeemployee.csv.tmp" "C:tempemployeeemployee.csv"

both the $RStat and @error return a zero value.  All of the commands from above appear to return a non-zero value if successful.  When I look at the temp folder the employee.csv is not created.

Can anyone point me in the right direction?

Link to comment
Share on other sites

Run returns the PID of the program being run, if there's no error the @error value will be zero, if there is an error then it will be anything but zero. So, if the @error is not returning zero, you have a problem. Have you tried the FileCopy function in AutoIt instead?

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

Link to comment
Share on other sites

I need to be able to concatenate two files A+B into one file "C".  The Filecopy command seems to only work with one file.  Short of reading both file in a loop and writting them out to the same file in append mode seems to be the only option.  The variable $RStat and @error in my previous example both return a 0.  when you look at the folder where the final file is suppose to be created there is nothing there.

Link to comment
Share on other sites

This what I tested with and gives expected results.

If Not FileExists('1.txt') Then FileWrite('1.txt', '1' & @CRLF)
If Not FileExists('2.txt') Then FileWrite('2.txt', '2' & @CRLF)

$pid = Run('"' & @ComSpec & '" /c copy 1.txt + 2.txt 3.txt', '', @SW_HIDE, 8)
$merged = _StdOutRead($pid)
ConsoleWrite($merged & @CRLF)

; C:\temp\employee exists

$Tmp_EmpFileFullFN = 'C:\temp\employee\employee.csv.tmp'
$EmpFileFullFN = 'C:\temp\employee\employee.csv'

If Not FileExists($Tmp_EmpFileFullFN) Then FileWrite($Tmp_EmpFileFullFN, '1' & @CRLF)

$cmd = @ComSpec & ' /c copy ' & '"' & $Tmp_EmpFileFullFN & '" "' & $EmpFileFullFN & '"'
$RStat = Run($cmd, "",  @SW_MAXIMIZE, 8)
$merged = _StdOutRead($RStat)
ConsoleWrite($merged & @CRLF)
ConsoleWrite($cmd & " (" & $RStat & ") (" & @error & ")" & @CRLF)

$pid = Run('"' & @ComSpec & '" /c where cmd.exe', '', @SW_HIDE, 8)
$merged = _StdOutRead($pid)
MsgBox(0, 'Where cmd.exe', @ComSpec & @CRLF & $merged & @CRLF & 'C:\WINDOWS\cmd.exe?')

Func _StdOutRead($pid)
    Local $output
    Do
        Sleep(10)
        $output &= StdOutRead($pid)
    Until @error
    Return $output
EndFunc

Output:

1.txt
2.txt
        1 file(s) copied.

        1 file(s) copied.

C:\Windows\system32\cmd.exe /c copy "C:\temp\employee\employee.csv.tmp" "C:\temp\employee\employee.csv" (4888) (0)

Notice cmd.exe is in the system directory.

Msgbox:

---------------------------
Where cmd.exe
---------------------------
C:\Windows\system32\cmd.exe

C:\Windows\System32\cmd.exe



C:\WINDOWS\cmd.exe?
---------------------------
OK   
---------------------------

3.txt

1
2

employee.csv

1

All passed the test. So I am unsure of what is happening to your test. :think:

Link to comment
Share on other sites

I have modfied the script you gave me just a bit and still no luck

$Tmp_EmpFileFullFN = 'C:tempemployeeemployee.csv.tmp'
$EmpFileFullFN = 'C:tempemployeeemployee.csv'
$EmpFileCustFullFN = 'C:tempemployeeCust.csv'

If Not FileExists($Tmp_EmpFileFullFN) Then FileWrite($Tmp_EmpFileFullFN, '1' & @CRLF)
Local $ComSpec = @ComSpec & "system32"

$pid = Run('"' & $ComSpec & '" dir /c ', '', @SW_MAXIMIZE, 8)
$merged = _StdOutRead($pid)
MsgBox(0, 'Dir ', $merged & @CRLF)

$cmd = $ComSpec & ' /c copy ' & '"' & $Tmp_EmpFileFullFN & '"+"' & $EmpFileCustFullFN & '" "' & $EmpFileFullFN & '"'
$RStat = Run($cmd, "",  @SW_MAXIMIZE, 8)
$merged = _StdOutRead($RStat)
ConsoleWrite($merged & @CRLF)
ConsoleWrite($cmd & " (" & $RStat & ") (" & @error & ")" & @CRLF)

$pid = Run('"' & $ComSpec & '" dir /c ', '', @SW_MAXIMIZE, 8)
$merged = _StdOutRead($pid)
MsgBox(0, 'Dir', $merged & @CRLF)

Func _StdOutRead($pid)
    Local $output
    Do
        Sleep(10)
        $output &= StdOutRead($pid)
    Until @error
    Return $output
EndFunc

I have attached a screen print of the debugger output and the dos window with the contents of each file displayed after the script has run.  The variables $RStat and @error are both zero and the veriable $merged show no value.  Not sure if they are null or blank but nothing displays in the msgbox.

post-38312-0-64961000-1384554890_thumb.j

Link to comment
Share on other sites

Modified it one last time with the output window below

$Tmp_EmpFileFullFN = 'C:tempemployeeemployee.csv.tmp'
$EmpFileFullFN = 'C:tempemployeeemployee.csv'
$EmpFileCustFullFN = 'C:tempemployeeCust.csv'

If Not FileExists($Tmp_EmpFileFullFN) Then FileWrite($Tmp_EmpFileFullFN, '1' & @CRLF)
Local $ComSpec = @ComSpec & "system32"

$pid = Run('"' & $ComSpec & '" dir /c ', '', @SW_MAXIMIZE, 8)
$merged = _StdOutRead($pid)
;MsgBox(0, 'Dir ', $merged & @CRLF)
ConsoleWrite('Line ' & @ScriptLineNumber & ' Length of $merged = [' & StringLen($merged) & ']' & @CRLF)

$cmd = $ComSpec & ' /c copy ' & '"' & $Tmp_EmpFileFullFN & '"+"' & $EmpFileCustFullFN & '" "' & $EmpFileFullFN & '"'
$RStat = Run($cmd, "",  @SW_MAXIMIZE, 8)
$merged = _StdOutRead($RStat)
;ConsoleWrite($merged & @CRLF)
ConsoleWrite('Line ' & @ScriptLineNumber & ' Length of $merged = [' & StringLen($merged) & ']' & @CRLF)
ConsoleWrite($cmd & " (" & $RStat & ") (" & @error & ")" & @CRLF)

$pid = Run('"' & $ComSpec & '" dir /c ', '', @SW_MAXIMIZE, 8)
$merged = _StdOutRead($pid)
;MsgBox(0, 'Dir', $merged & @CRLF)
ConsoleWrite('Line ' & @ScriptLineNumber & ' Length of $merged = [' & StringLen($merged) & ']' & @CRLF)

Func _StdOutRead($pid)
    Local $output
    Do
        Sleep(10)
        $output &= StdOutRead($pid)
    Until @error
    Return $output
EndFunc

Output window----------------------------------------------------------

Line 61 Length of $merged = [0]

Line 87 Length of $merged = [0]

C:\Windows\System32\ /c copy "C:tempemployeeemployee.csv.tmp"+"C:tempemployeeCust.csv" "C:tempemployeeemployee.csv" (0) (0)

Line 113 Length of $merged = [0]
 

Link to comment
Share on other sites

Thanks for the picture. So you are using Windows XP. $ComSpec is C:\Windows\System32\ and the command prompt window title is C:\Windows\System32\cmd.exe. The title is correct though $ComSpec is not correct. C:\Windows\System32\ will not work well with parameters so I would expect failure in your last attempts.

If I test $ComSpec as your script sets it, I get C:\Windows\System32\cmd.exesystem32 which I would expect from system32 being appended to @ComSpec. It looks as if the ComSpec environmental variable path has been changed. Still does not explain how the 1st post has cmd.exe appended, hmm.

Try this in your command prompt.

echo %ComSpec%

You should get a return the same as your prompt window which would be  C:\Windows\System32\cmd.exe. If it does not then try the script below.

$regkeyEnvironment = 'HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
$regdatComSpec = '%SystemRoot%\system32\cmd.exe'

; check if parameter passed to the script
If $CMDLINE[0] Then
    ; only /update parameter
    If $CMDLINE[1] = '/update' Then
        _Update()
    EndIf
    Exit
EndIf

; get ComSpec path from registry. Expect %SystemRoot%\system32\cmd.exe
$ComSpec = RegRead($regkeyEnvironment, 'ComSpec')
MsgBox(0, 'ComSpec path from registry', $ComSpec)

If $ComSpec And $ComSpec <> $regdatComSpec Then
    ; this checks if the expected path to cmd.exe exists
    If Not FileExists(EnvGet('SystemRoot') & '\system32\cmd.exe') Then
        MsgBox(0x40030, @ScriptName, 'Not found ' & EnvGet('SystemRoot') & '\system32\cmd.exe')
        Exit 1
    EndIf
    ; prompt to update the registry. Will start a 2nd instance of script if yes
    If MsgBox(0x40024, @ScriptName, 'Do you want to update the ComSpec path in the registry?') = 6 Then ; yes
        If IsAdmin() Then
            _Update()
        Else
            ; if not admin start another instance with runas verb
            ShellExecuteWait('"' & @AutoItExe & '"', '/AutoIt3ExecuteScript "' & @ScriptFullPath & '" /update', '', 'runas')
        EndIf
    EndIf
EndIf

MsgBox(0, @ScriptName, 'Task is finished')

Exit

Func _Update()
    If RegWrite($regkeyEnvironment, 'ComSpec', 'REG_EXPAND_SZ', $regdatComSpec) Then
        ; update the environment as to the change. May need to restart apps that depend on ComSpec path or at worst, restart OS
        EnvUpdate()
        MsgBox(0x40000, @ScriptName, 'Registry updated')
    Else
        MsgBox(0x40000, @ScriptName, 'Registry not updated')
    EndIf
EndFunc

Tested on Windows 7. The script will check the registry value of ComSpec and will show a MsgBox with hopefully %SystemRoot%system32cmd.exe in it. If not, then you may see another MsgBox to update the registry value of ComSpec. If acceptable, then click yes to write %SystemRoot%system32cmd.exe as the value of ComSpec. A second instance of the script may do the change if you are not admin.

Perhaps you should check the rest of the environmental variables by just typing set in the command prompt and check the return.

set

If fixed, then @ComSpec may work better in your script. :)

Link to comment
Share on other sites

I made the appropriate changes to the WinReg and things seem to be working better.  I checked several other workstations and they all had the comspec set correctly.  Not sure why mine was different.  I rebooted the workstation and then checked again.  The WinReg again had the correct values so it does not appear to be the work of some program or group policy setting it to the wrong value.  For not it works. Thanks.

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...