MickFarrell Ответов: 2

Setwindowtext в режиме администратора не работает


Привет,

Эта проблема заставляет меня рвать на себе волосы?? У меня есть приложение, которое не отображает текст для некоторых пользователей. Я не могу воспроизвести эту проблему, так как она прекрасно работает для меня. Я действительно обнаружил, что если я запускаю приложение от имени администратора, то возникает проблема?

При запуске приложения от имени администратора функция SetWindowText не работает. При запуске приложения в обычном режиме SetWindowText работает нормально.

Если я попытаюсь отладить приложение в Visual Studio 2017, запустив его в режиме администратора, оно будет работать нормально, поэтому я не вижу, в чем проблема. Я отобразил окно сообщения непосредственно перед вызовом SetWindowText, и окно messabe отображает текст правильно, но SetWindowText пуст?

Вот пример тестового кода.


// Declared in the Header file
WCHAR m_UserPrompt[128];



// CPP implementation file
void CUserPromptDlg::GetDisplayPrompt(WCHAR *pUserPrompt)
{
	wcscpy(pUserPrompt, L"Test message");
}


void CUserPromptDlg::TestFunc1()
{
	GetDisplayPrompt(m_UserPrompt);
	AfxMessageBox(m_UserPrompt);
	SetDlgItemTextW(IDS_USER_PROMPT, m_UserPrompt);
}


Что я уже пробовал:

Я перепробовал все, что мог придумать, но не могу понять, почему это работает для 85% пользователей, а не для остальных 15%??

KarstenK

вы пропустили добавление кода для вашей ошибки SetWindowText!

MickFarrell

Привет, он включен выше, не знаю, почему вы его не видите, но вот он

// Объявлено в заголовочном файле
Тип данных wchar m_UserPrompt[128];



/ Файл реализации / КПП
void CUserPromptDlg::GetDisplayPrompt(WCHAR *pUserPrompt)
{
wcscpy(pUserPrompt, L"Тестовое сообщение");
}


void CUserPromptDlg::TestFunc1()
{
GetDisplayPrompt(m_UserPrompt);
AfxMessageBox(m_UserPrompt);
SetDlgItemTextW(IDS_USER_PROMPT, m_UserPrompt);
}

2 Ответов

Рейтинг:
2

Richard MacCutchan

У меня была похожая проблема с simple Messagebox вызовы, когда обработчик WM_PAINT не вызывает BeginPaint / EndPaint последовательность. Вам может понравиться, чтобы проверить, если это возможно.

[редактировать]

// CPP implementation file
void CUserPromptDlg::GetDisplayPrompt(WCHAR *pUserPrompt)
{
	wcscpy(pUserPrompt, L"Test message");
}


void CUserPromptDlg::TestFunc1()
{
	GetDisplayPrompt(m_UserPrompt);
	AfxMessageBox(m_UserPrompt);
	SetDlgItemTextW(IDS_USER_PROMPT, m_UserPrompt);
}


Похоже, вы используете разные переменные для текста.

[/редактировать]


MickFarrell

Привет Ричард,

Я упростил код, насколько это возможно, чтобы проверить и я использую только базового класса cdialog без обработки сообщения WM_PAINT сообщение. Тот же код работает нормально, но не отображает текст при запуске в режиме администратора?

MickFarrell

Привет Ричард,

Я упростил код, насколько это возможно, чтобы проверить и я использую только базового класса cdialog без обработки сообщения WM_PAINT сообщение. Тот же код работает нормально, но не отображает текст при запуске в режиме администратора?

Richard MacCutchan

Смотрите мое обновленное решение.

MickFarrell

Привет, Ричард, один из них-указатель на массив WCHAR. m_UserPrompt объявляется в заголовочном файле.

Решение 1: если я переместил m_UserPrompt из заголовочного файла и объявил его в функции класса TestFunc1() как локальную переменную, то он работает нормально.

Решение 2: Если я скопирую содержимое m_UserPrompt в строку CString, она будет работать нормально.

Это меня совершенно озадачило?? Я убежден, что проблема связана с юникодом, но я не могу понять ее?

Richard MacCutchan

Извините, но здесь слишком много деталей, которые мы не можем увидеть. Если вам нужно переместить что-то из заголовка в файл реализации, чтобы заставить его работать, то ваше определение класса должно быть неверным. Вам нужно пройти через весь ваш код строка за строкой, чтобы убедиться, что он завершен, и что вы не ошиблись в чем-то.

MickFarrell

Привет, Ричард, Что касается вашего предыдущего решения, то чего же не хватало? Вы сказали: "Вы, кажется, используете разные переменные для текста", но это есть в коде, вызывающем функцию для установки текста?

Проблема в заголовочном файле не приведет к тому, что текст будет работать только в режиме администратора. Запуск в режиме администратора-это единственный способ "я" воспроизвести проблему, для некоторых пользователей это просто происходит, когда они запускают ее нормально

Я действительно ценю ваше время, вклад и предложения, и я действительно считаю, что проблема глубже, чем небольшой образец кода, который я предоставил, но я надеюсь, что кто-то, возможно, столкнулся с чем-то подобным в прошлом и мог бы указать мне в другом направлении. :-)

Richard MacCutchan

Извините, я неправильно прочитал код. Однако где же декларация о том, что m_UserPrompt?

MickFarrell

Привет Ричард,

Он объявлен в заголовочном файле. Я действительно включил его в свой первоначальный пост.

// Объявлено в заголовочном файле
Тип данных wchar m_UserPrompt[128];

Richard MacCutchan

Извините, но я все больше запутываюсь. Ваш первоначальный вопрос гласит, что SetWindowText иногда это не работает. Ваш пример использует SetDlgItemTextW а это не совсем одно и то же. Кроме того, вы показали только части своего кода. Я думаю, что вам нужно начать снова с нового вопроса, который показывает полное определение вашего класса (будь то окно или диалог) и те части реализации, которые действительно вызывают проблему.

Наконец, вы должны знать, что SetDlgItemTextW должны вернуться false если это не удается, то в этот момент вам нужно позвонить GetLastError чтобы выяснить почему. Я не говорю, что это то, что происходит, но это нужно проверить, учитывая вашу проблему.

MickFarrell

Это программа unicode, поэтому SetWindowText-это SetWindowTextW. SetWindowText (SetWindowTextW или SetWindowTextA) не возвращает значения. Вы путаете win32 api ::SetWindowText (::SetWindowTextW или ::SetWindowTextA), который возвращает true или false.

Вы дали мне идею, я попробую вызвать версию win32 и посмотреть, что она возвращает? спасибо

Richard MacCutchan

Извините, я не пользовался MFC уже много лет и предполагал (глупо), что они сделают то же самое. Я также отметил комментарий Стивеба выше, о идентификаторе, который вы используете в своем звонке. Вы уверены в этом IDS_USER_PROMPT является ли допустимым идентификатор элемента управления диалогового окна?

MickFarrell

Привет, Ричард, я проверил, чтобы убедиться, что IDS_USER_PROMPT id уникален, и я даже добавил новое поле редактирования в диалоговое окно для проверки, и текст по-прежнему остается пустым в новом поле редактирования.

Я действительно пытался использовать ::SetWindowText и ::SetWindowTextW (::SetWindowTextA не будет компилироваться как проект UNICODE), и они оба возвращают true, даже если они не отображают текст.

У меня есть несколько тестировщиков, которые проводят обширное тестирование на Azure, и мы действительно нашли кое-что очень интересное.

Tester1 входит в Azure с помощью учетной записи Пользователя Azure "AzureTest1", и текст отсутствует.

Tester2 входит в ту же учетную запись Azure "AzureTest1", и для него появляется текст.

Tester1 использовал свой второй компьютер для входа в Azure с помощью учетной записи Azure "AzureTest1", и текст появляется.

Похоже, это как-то связано с настройками на локальном компьютере, которые были переданы в учетную запись Azure при входе в систему? Они проверяют местные и региональные настройки, чтобы увидеть, если они могут сузить его

Еще раз спасибо Ричарду за ваше время и вклад, всегда очень хорошо получить какие-то другие идеи.






Richard MacCutchan

"проверьте уникальность идентификатора IDS_USER_PROMPT"
Нас больше беспокоило, был ли это на самом деле идентификатор элемента управления или идентификатор строки ресурса.

MickFarrell

Да, это идентификатор фактического элемента управления редактированием, а не идентификатор строки ресурса.

Richard MacCutchan

Я был почти уверен, что так и должно быть, иначе это, вероятно, никогда бы не сработало. Но в подобной ситуации стоит проверить все и вся.

MickFarrell

Я согласен, я бы лучше перепроверил, чем предположил. Мы собираемся вернуться к предыдущему SDK, когда проблема отсутствовала, и запустить некоторое тестирование.

Весь проект состоит из более чем 1 миллиона строк кода со смесью c, c++, clr, c#, .net, ASP.net и есть только около 10 мест, где это происходит, и это происходит только при очень странных условиях, которые мы еще не определили.

У меня есть обходной путь, но я не хочу его реализовывать, если нам это действительно не нужно.

Рейтинг:
1

steveb

Используют ли ваши другие 15% пользователей конфигурацию компьютерного языка, установленную в EN(US)?


MickFarrell

Привет,

Я проверю у нескольких пользователей, есть ли у них разные языковые настройки на своих компьютерах.

Если это проблема с языковыми настройками, то почему это происходит со мной, когда я работаю в режиме администратора, но не тогда, когда я этого не делаю?

MickFarrell

Я проверил 4 пользователя, и все они имеют свои языковые и региональные настройки, установленные на EN(US). У одного из этих пользователей есть проблема с дисплеем

steveb

Обычно он просто отображает мусорные символы, если вы помещаете коды en(us) на кириллицу или японский язык. Кроме того, поскольку вы помещаете строку, по тому, как она выглядит, в статический текстовый элемент управления, убедитесь, что она достаточно широка. Насколько я помню, когда статический текст не помещается в поле, он остается пустым. В отличие от редактирования текстового поля.

И самое главное: вызовите UpdateData(FALSE) после того, как ваш m_UserPrompt привязан к обновлениям подпрограмм DDX_

MickFarrell

Привет, Стив, m_UserPrompt не привязан ни к одному DDX, это просто массив WCHAR с большим количеством места. Текстовое поле в диалоговом окне имеет достаточно места и отображает текст префектно, когда он не запускается от имени администратора.

steveb

Хорошо. Я не являюсь администратором на своей машине. Я только что создал приложение на основе диалогового окна и использовал именно ваш код (я вызвал TestFunc1() из OnInitDialog). И это прекрасно работает независимо от того, бежал ли я как администратор или обычный пользователь. В вашем коде не хватает чего-то еще. Не могу сказать, что именно.

Кстати, поскольку вы используете MFC, вы можете использовать CString вместо WCHAR[128] и DDX_ привязать его к элементу управления. Вызовите UpdateData(FALSE) после изменения значения CString. Если вы строите UNICODE CString, то он становится CStringW.

Также я заметил следующее: Ваш идентификатор элемента управления-IDS_USER_PROMPT. Это, может быть, ничего. Но мастер приложений MSVC использует префикс IDS_ для строк ресурсов и префикс IDC_ для элементов управления. Дважды проверьте, что ваш IDS_USER_PROMPT является не "ресурсом Строковой таблицы", а фактическим идентификатором элемента управления

MickFarrell

Все хорошие моменты Стив, и да, по умолчанию это IDC_ я попытался добавить новый элемент управления редактированием и оставил его в default define IDC_EDIT, и даже новый элемент управления редактированием не работает. Я почти уверен, что ваше предложение сработает, если я использую следующий код (добавил CString), он работает 100% времени для всех пользователей:

void CUserPromptDlg::TestFunc1()
{
GetDisplayPrompt(m_UserPrompt);
Однако темп = m_UserPrompt
SetDlgItemTextW(IDS_USER_PROMPT, temp);
}

Я удалил AfxMessageBox(m_UserPrompt), так как это только для тестирования, оно не имеет никакого влияния.

Я думаю, что вы, возможно, что-то напутали с вашим предыдущим вопросом о языке и региональных настройках. Мы создали несколько новых тестовых учетных записей в Azure для некоторых тестировщиков.

Tester1 входит в Azure с помощью учетной записи Пользователя Azure "AzureTest1", и текст отсутствует.

Tester2 входит в ту же учетную запись Azure "AzureTest1", и для него появляется текст.

Tester1 использовал свой второй компьютер для входа в Azure с помощью учетной записи Azure "AzureTest1", и текст появляется.

Похоже, это как-то связано с настройками на локальном компьютере, которые были переданы в учетную запись Azure при входе в систему? Они проверяют местные и региональные настройки, чтобы увидеть, если они могут сузить его

Спасибо Вам за помощь и предложения, Стив!