न्यूनतम प्रतिलिपि प्रस्तुत करने योग्य कोड प्रस्तुत करने के लिए मैंने CreateProcessW() का उपयोग करके किसी दिए गए स्थान से फ़ाइल को हटाने के लिए एक कोड लिखा था। फ़ाइल हटाई नहीं जाती है। यह जानने में कुछ मदद वास्तव में उपयोगी होगी कि यह क्यों काम नहीं कर रहा है।

dprintf(("Error %d", GetLastError()));
STARTUPINFO si = { sizeof(STARTUPINFO), 0 };
si.cb = sizeof(si);
PROCESS_INFORMATION pi = { 0 };
LPWSTR AppName = L"C:\\Windows\\System32\\cmd.exe";
string bstr = "C:\\Windows\\System32\\cmd.exe /C del"+trans_loc+"a.rtf";
LPWSTR Command = new WCHAR[bstr.length()];
int wchars_num = MultiByteToWideChar(CP_UTF8, 0, bstr.c_str(), -1, NULL, 0);
MultiByteToWideChar(CP_UTF8, 0, bstr.c_str(), -1, Command, wchars_num);
DWORD res = CreateProcessW(AppName, Command, 0, 0, 0, DETACHED_PROCESS, 0, 0, &si, &pi);

WaitForSingleObject(pi.hProcess, INFINITE);

परिभाषित करें TRANSCRIPT_LOCATION "C:\Users\Administrator\Desktop\" यह हटाए जाने वाली फ़ाइल का स्थान है

GetLastError () 50 (ERROR_NOT_SUPPORTED) और res = 1 का मान लौटाता रहता है

0
Praful Srivastava 18 मार्च 2020, 01:15
क्या आपने GetLastError() को देखा? क्या आपने इसे बिल्कुल डीबग किया था?
 – 
tenfour
18 मार्च 2020, 01:18
हाँ, यह 50 (ERROR_NOT_SUPPORTED) देता रहता है।
 – 
Praful Srivastava
18 मार्च 2020, 01:24
1
यह स्पष्ट नहीं है कि जब आप वास्तव में gcloud निष्पादित करना चाहते हैं तो आप cmd.exe क्यों चलाना चाहते हैं। अस्थायी रूप से /c के बजाय /k का उपयोग करें ताकि आप त्रुटि संदेश देख सकें। फ़ाइल पथ के रूप में सरल हो सकता है जिसमें डबल-कोट्स की आवश्यकता होती है। और त्रुटि प्रबंधन को ठीक करें, GetLastError() केवल तभी मान्य है जब CreateProcess FALSE लौटाता है।
 – 
Hans Passant
18 मार्च 2020, 01:46

2 जवाब

मेरा पहला विचार यह है कि

LPWSTR Command = new WCHAR[bstr.length()];

सही नहीं है। शायद

LPWSTR Command = new WCHAR[bstr.length() + 1];

काम करेगा। स्मृति आवंटित करने के लिए wchars_num का उपयोग करना एक बेहतर विकल्प है।

की बजाय

LPWSTR Command = new WCHAR[bstr.length()];
int wchars_num = MultiByteToWideChar(CP_UTF8, 0, bstr.c_str(), -1, NULL, 0);
MultiByteToWideChar(CP_UTF8, 0, bstr.c_str(), -1, Command, wchars_num);
DWORD res = CreateProcessW(AppName, Command, 0, 0, 0, DETACHED_PROCESS, 0, 0, &si, &pi);

उपयोग

int wchars_num = MultiByteToWideChar(CP_UTF8, 0, bstr.c_str(), -1, NULL, 0);
LPWSTR Command = new WCHAR[wchars_num];
MultiByteToWideChar(CP_UTF8, 0, bstr.c_str(), -1, Command, wchars_num);
DWORD res = CreateProcessW(AppName, Command, 0, 0, 0, DETACHED_PROCESS, 0, 0, &si, &pi);

दूसरा मुद्दा यह है कि शायद del कमांड लिखते समय आप एक स्पेस कैरेक्टर से चूक गए।

string bstr = "C:\\Windows\\System32\\cmd.exe /C del " + trans_loc + "a.rtf";
//                                                  ^^
2
R Sahu 18 मार्च 2020, 01:33
धन्यवाद, मैंने बदलाव जोड़ा। लेकिन मसला अब भी जस का तस
 – 
Praful Srivastava
18 मार्च 2020, 01:30
ठीक है, "डेल" कमांड के बाद जगह जोड़ने से चाल चली। बहुत - बहुत धन्यवाद। मैंने अपनी मूल समस्या पर वापस जाने के लिए प्रश्न को थोड़ा संपादित किया है (डेल केवल न्यूनतम प्रतिलिपि प्रस्तुत करने योग्य उदाहरण के लिए था)।
 – 
Praful Srivastava
18 मार्च 2020, 01:38
Bstr gcloud चलाने और टेक्स्टफाइल में आउटपुट प्राप्त करने का आदेश है। केवल टेक्स्टफाइल बनाया जाता है। gcloud प्रांप्ट कभी नहीं आता।
 – 
Praful Srivastava
18 मार्च 2020, 01:42
2
प्रश्न को बदलना ताकि उत्तर अब फिट न हो, अच्छा नहीं है। आपको अपना मूल प्रश्न छोड़ देना चाहिए था और इस उत्तर को स्वीकार कर लिया और फिर एक नया प्रश्न पूछा। यदि आप संपादित लिंक पर क्लिक करते हैं, तो आप पुराने संस्करण पर वापस जा सकते हैं।
 – 
Ted Lyngmo
18 मार्च 2020, 01:43
1
ओह ठीक है। मैं एक नया प्रश्न पूछूंगा और इसे फिर से संपादित करूंगा।
 – 
Praful Srivastava
18 मार्च 2020, 01:45

मुझे आपके कोड में कई समस्याएं दिखाई दे रही हैं:

  • LPWSTR AppName = L"C:\\Windows\\System32\\cmd.exe"; C++11 और बाद के संस्करणों में संकलित नहीं होता है। इसके बजाय आपको (और चाहिए) LPCWSTR का उपयोग करना चाहिए, क्योंकि एक स्ट्रिंग अक्षर const डेटा है, और LPCWSTR const WCHAR का सूचक है डेटा, लेकिन LPWSTR गैर-const WCHAR डेटा का सूचक है।

  • string bstr = "C:\\Windows\\System32\\cmd.exe /C del"+trans_loc+"a.rtf"; में, आप del कमांड और डिलीट करने के लिए फ़ाइल नाम के बीच एक आवश्यक स्पेस कैरेक्टर को मिस कर रहे हैं।

  • LPWSTR Command = new WCHAR[bstr.length()]; में, आप एक नल टर्मिनेटर के लिए पर्याप्त जगह आवंटित नहीं कर रहे हैं। साथ ही, आपको वैसे भी परिवर्तित लंबाई के लिए bstr.length() का उपयोग नहीं करना चाहिए, क्योंकि इस बात की कोई गारंटी नहीं है कि परिवर्तित स्ट्रिंग मूल स्ट्रिंग से बड़ी नहीं होगी। वास्तविक रूपांतरित लंबाई (जो आप कर रहे हैं) की गणना करने के लिए आपको MultiByteToWideChar() एक बार NULL आउटपुट बफर के साथ कॉल करना चाहिए, फिर मेमोरी आवंटित करें (जो आप नहीं कर रहे हैं - आप बहुत जल्द आवंटित कर रहे हैं!) , फिर वास्तविक रूपांतरण करने के लिए MultiByteToWideChar() को फिर से कॉल करें।

  • आप आवंटित मेमोरी को लीक कर रहे हैं (आप delete[] Command; को कॉल नहीं कर रहे हैं)। मैं new WCHAR[] के बजाय std::wstring या std::vector<WCHAR> का उपयोग करने का सुझाव दूंगा।

  • आप कहते हैं कि res को 1 पर सेट किया जा रहा है, जिसका अर्थ है कि CreateProcessW() वास्तव में cmd.exe चलाने में सफल है (अब, क्या cmd.exe सफल है अपने आदेश को क्रियान्वित करना एक अलग मामला है - का उपयोग करें GetExitCodeProcess() इसका पता लगाने के लिए), और इस प्रकार GetLastError() का वापसी मूल्य अर्थहीन है! CreateProcessW() को कॉल करने से पहले GetLastError() पहले कॉल करना निश्चित रूप से सार्थक है

  • आप WaitForSingleObject() को कॉल कर रहे हैं, भले ही CreateProcessW() सफल हो या विफल।

इसके बजाय इसे आजमाएं:

STARTUPINFO si = {};
si.cb = sizeof(si);
PROCESS_INFORMATION pi = {};

std::string bstr = "C:\\Windows\\System32\\cmd.exe /C del \"" + trans_loc + "a.rtf\"";

int wchars_num = MultiByteToWideChar(CP_UTF8, 0, bstr.c_str(), bstr.length(), NULL, 0);
if (wchars_num == 0)
{
    dprintf(("MultiByteToWideChar Error %d", GetLastError()));
}
else
{
    std::vector<WCHAR> Command(wchars_num + 1);
    MultiByteToWideChar(CP_UTF8, 0, bstr.c_str(), bstr.length(), Command.data(), wchars_num);

    if (!CreateProcessW(nullptr, Command.data(), nullptr, nullptr, FALSE, DETACHED_PROCESS, nullptr, nullptr, &si, &pi))
    {
        dprintf(("CreateProcessW Error %d", GetLastError()));
    }
    else
    {
        WaitForSingleObject(pi.hProcess, INFINITE);

        DWORD dwExitCode = 0;
        GetExitCodeProcess(pi.hProcess, &dwExitCode);
        dprintf(("cmd.exe Exit Code %d", dwExitCode));

        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
    }
}

या, यदि आप विंडोज 10 बिल्ड 17035 या बाद के संस्करण का उपयोग कर रहे हैं और आपने अपनी विंडोज सेटिंग्स में "बीटा: यूज यूनिकोड यूटीएफ -8 फॉर वर्ल्डवाइड लैंग्वेज सपोर्ट" विकल्प को सक्षम किया है (या, अगर trans_loc में कोई गैर-ASCII शामिल नहीं है , गैर-उपयोगकर्ता-स्थानीय वर्ण), तो किसी भी MultiByteToWideChar() रूपांतरण की आवश्यकता नहीं है:

STARTUPINFO si = {};
si.cb = sizeof(si);
PROCESS_INFORMATION pi = {};

std::string Command = "C:\\Windows\\System32\\cmd.exe /C del \"" + trans_loc + "a.rtf\"";

if (!CreateProcessA(nullptr, const_cast<char*>(Command.c_str()), nullptr, nullptr, FALSE, DETACHED_PROCESS, nullptr, nullptr, &si, &pi))
{
    dprintf(("CreateProcessA Error %d", GetLastError()));
}
else
{
    WaitForSingleObject(pi.hProcess, INFINITE);

    DWORD dwExitCode = 0;
    GetExitCodeProcess(pi.hProcess, &dwExitCode);
    dprintf(("cmd.exe Exit Code %d", dwExitCode));

    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
}

कहा जा रहा है, एक बेहतर विकल्प यह होगा कि शुरुआत करने के लिए std::string के बजाय केवल std::wstring का उपयोग करें:

STARTUPINFO si = {};
si.cb = sizeof(si);
PROCESS_INFORMATION pi = {};

// make sure trans_loc is std::wstring instead of std::string...
std::wstring bstr = L"C:\\Windows\\System32\\cmd.exe /C del \"" + trans_loc + L"a.rtf\"";

if (!CreateProcessW(nullptr, Command.data(), nullptr, nullptr, FALSE, DETACHED_PROCESS, nullptr, nullptr, &si, &pi))
{
    dprintf(("CreateProcessW Error %d", GetLastError()));
}
else
{
    WaitForSingleObject(pi.hProcess, INFINITE);

    DWORD dwExitCode = 0;
    GetExitCodeProcess(pi.hProcess, &dwExitCode);
    dprintf(("cmd.exe Exit Code %d", dwExitCode));

    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
}

बेशक, सबसे आसान उपाय यह होगा कि आप cmd.exe / C del का बिल्कुल भी उपयोग न करें, बल्कि इसके बजाय DeleteFileW():

// make sure trans_loc is std::wstring instead of std::string...
std::wstring bstr = trans_loc + L"a.rtf";

if (!DeleteFileW(bstr.c_str()))
{
    dprintf(("DeleteFileW Error %d", GetLastError()));
}

या, यदि आप UTF-8 एन्कोडेड std::string का उपयोग करने का आग्रह करते हैं:

std::string bstr = trans_loc + "a.rtf";

int wchars_num = MultiByteToWideChar(CP_UTF8, 0, bstr.c_str(), bstr.length(), NULL, 0);
if (wchars_num == 0)
{
    dprintf(("MultiByteToWideChar Error %d", GetLastError()));
}
else
{
    std::vector<WCHAR> wstr(wchars_num + 1);
    MultiByteToWideChar(CP_UTF8, 0, bstr.c_str(), bstr.length(), wstr.data(), wchars_num);

    if (!DeleteFileW(wstr.c_str()))
    {
        dprintf(("DeleteFileW Error %d", GetLastError()));
    }
}

या, यदि आप UTF-8 समर्थन सक्षम के साथ Windows 10 का उपयोग कर रहे हैं (या, यदि trans_loc में कोई गैर-ASCII, गैर-उपयोगकर्ता-स्थानीय वर्ण शामिल नहीं है):

std::string bstr = trans_loc + "a.rtf";

if (!DeleteFileA(bstr.c_str()))
{
    dprintf(("DeleteFileA Error %d", GetLastError()));
}
1
Remy Lebeau 18 मार्च 2020, 20:55
1
इन सबके अलावा, bstr किसी ऐसी चीज़ के लिए एक भयानक नाम है जो Windows BSTR नहीं है।
 – 
Ben Voigt
18 मार्च 2020, 17:45