Windows SAPI错误:'GetVersionExA':已宣布弃用

问题描述 投票:0回答:1

所以我一生中想要做的就是拥有一个程序,在该程序中我可以说“ Hey Computer”,它以“ Hello”作为响应。因此,我将自己放在了任务上,经过一些研究产生了以下代码,但是每当我尝试通过Windows 10上的Visual Studio 2017对其进行编译时,都会收到此错误:'GetVersionExA':被声明为不赞成使用,但我不明白,因为我没有不要在我的代码中的任何地方调用该函数。

#include <sphelper.h>
#include <sapi.h>
#include <iostream>
#include <string>
#include <vector>
#include <locale>

const ULONGLONG grammarId = 0;
const wchar_t* ruleName1 = L"ruleName1";

int start_listening(const std::string& word);
ISpRecoGrammar* init_grammar(ISpRecoContext* recoContext, const std::string& command);
void get_text(ISpRecoContext* reco_context);
void check_result(const HRESULT& result);

ISpVoice * pVoice = NULL;
HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);

inline std::wstring s2w(const std::string &s, const std::locale &loc = std::locale())
{
    typedef std::ctype<wchar_t> wchar_facet;
    std::wstring return_value;
    if (s.empty())
    {
        return return_value;
    }
    if (std::has_facet<wchar_facet>(loc))
    {
        std::vector<wchar_t> to(s.size() + 2, 0);
        std::vector<wchar_t>::pointer toPtr = &to[0];
        const wchar_facet &facet = std::use_facet<wchar_facet>(loc);
        if (0 != facet.widen(s.c_str(), s.c_str() + s.size(), toPtr))
        {
            return_value = to.data();
        }
    }
    return return_value;
}

int main(int argc, char** argv)
{
    HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);
    std::string hello = "hello";

    start_listening("Hey computer");
    hr = pVoice->Speak(s2w(hello).c_str(), 0, NULL);
    return EXIT_SUCCESS;
}

// This function exits when the word passed as parameter is said by the user
int start_listening(const std::string& word)
{
    // Initialize COM library
    if (FAILED(::CoInitialize(nullptr))) {
        return EXIT_FAILURE;
    }

    std::cout << "You should start Windows Recognition" << std::endl;
    std::cout << "Just say \"" << word << "\"" << std::endl;

    HRESULT hr;

    ISpRecognizer* recognizer;
    hr = CoCreateInstance(CLSID_SpSharedRecognizer,
        nullptr, CLSCTX_ALL, IID_ISpRecognizer,
        reinterpret_cast<void**>(&recognizer));
    check_result(hr);

    ISpRecoContext* recoContext;
    hr = recognizer->CreateRecoContext(&recoContext);
    check_result(hr);

    // Disable context
    hr = recoContext->Pause(0);
    check_result(hr);

    ISpRecoGrammar* recoGrammar = init_grammar(recoContext, word);

    hr = recoContext->SetNotifyWin32Event();
    check_result(hr);

    HANDLE handleEvent;
    handleEvent = recoContext->GetNotifyEventHandle();
    if (handleEvent == INVALID_HANDLE_VALUE) {
        check_result(E_FAIL);
    }

    ULONGLONG interest;
    interest = SPFEI(SPEI_RECOGNITION);
    hr = recoContext->SetInterest(interest, interest);
    check_result(hr);

    // Activate Grammar
    hr = recoGrammar->SetRuleState(ruleName1, 0, SPRS_ACTIVE);
    check_result(hr);

    // Enable context
    hr = recoContext->Resume(0);
    check_result(hr);

    // Wait for reco
    HANDLE handles[1];
    handles[0] = handleEvent;
    WaitForMultipleObjects(1, handles, FALSE, INFINITE);
    get_text(recoContext);

    std::cout << "Hello user" << std::endl;

    recoGrammar->Release();
    ::CoUninitialize();

    system("PAUSE");
    return EXIT_SUCCESS;
}

/**
* Create and initialize the Grammar.
* Create a rule for the grammar.
* Add word to the grammar.
*/
ISpRecoGrammar* init_grammar(ISpRecoContext* recoContext, const std::string& command)
{
    HRESULT hr;
    SPSTATEHANDLE sate;

    ISpRecoGrammar* recoGrammar;
    hr = recoContext->CreateGrammar(grammarId, &recoGrammar);
    check_result(hr);

    WORD langId = MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH);
    hr = recoGrammar->ResetGrammar(langId);
    check_result(hr);
    // TODO: Catch error and use default langId => GetUserDefaultUILanguage()

    // Create rules
    hr = recoGrammar->GetRule(ruleName1, 0, SPRAF_TopLevel | SPRAF_Active, true, &sate);
    check_result(hr);

    // Add a word
    const std::wstring commandWstr = std::wstring(command.begin(), command.end());
    hr = recoGrammar->AddWordTransition(sate, NULL, commandWstr.c_str(), L" ", SPWT_LEXICAL, 1, nullptr);
    check_result(hr);

    // Commit changes
    hr = recoGrammar->Commit(0);
    check_result(hr);

    return recoGrammar;
}

void get_text(ISpRecoContext* reco_context)
{
    const ULONG maxEvents = 10;
    SPEVENT events[maxEvents];

    ULONG eventCount;
    HRESULT hr;
    hr = reco_context->GetEvents(maxEvents, events, &eventCount);

    // Warning hr equal S_FALSE if everything is OK 
    // but eventCount < requestedEventCount
    if (!(hr == S_OK || hr == S_FALSE)) {
        check_result(hr);
    }

    ISpRecoResult* recoResult;
    recoResult = reinterpret_cast<ISpRecoResult*>(events[0].lParam);

    wchar_t* text;
    hr = recoResult->GetText(SP_GETWHOLEPHRASE, SP_GETWHOLEPHRASE, FALSE, &text, NULL);
    check_result(hr);

    CoTaskMemFree(text);
}

void check_result(const HRESULT& result)
{
    if (result == S_OK) {
        return;
    }

    std::string message;

    switch (result) {

    case E_INVALIDARG:
        message = "One or more arguments are invalids.";

    case E_ACCESSDENIED:
        message = "Acces Denied.";

    case E_NOINTERFACE:
        message = "Interface does not exist.";

    case E_NOTIMPL:
        message = "Not implemented method.";

    case E_OUTOFMEMORY:
        message = "Out of memory.";

    case E_POINTER:
        message = "Invalid pointer.";

    case E_UNEXPECTED:
        message = "Unexpecter error.";

    case E_FAIL:
        message = "Failure";

    default:
        message = "Unknown : " + std::to_string(result);
    }

    throw std::exception(message.c_str());
}
c++ windows visual-studio visual-c++ sapi
1个回答
0
投票

GetVersionEx被包含的标题sphelper.h使用。使用它来检查功能SpGetDescription()是否在Vista或更高版本上运行。您可以通过针对8.1 SDK版本而不是10来解决此问题。但是,Windows 10 SDK中附带的MS SAPI API使用Windows 10中不推荐使用的功能是很糟糕的。我想说这是一个MS问题。

或者,这将起作用:

#define FKG_FORCED_USAGE 1
#include <sphelper.h>
#undef FKG_FORCED_USAGE
© www.soinside.com 2019 - 2024. All rights reserved.