|
I have used binding for more than 10 years in Windows Forms projects.
|
|
|
|
|
If one never leaves the Designer, and believes all the "no code behind", then one never learns about Windows Forms binding, etc. It's when you start writing your own framework(s) and patterns that all this starts to come to the surface. For some, that is a bad thing ("details").
It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it.
― Confucian Analects: Rules of Confucius about his food
|
|
|
|
|
Binding is Good(Less coding) and Bad(more code to control)
If you want full control on your form workflow, don't use binding
If you bind a control (textbox) to datasource (access or mssql) to field ID (AutoNumber) and you want to add new record, the textbox will display -1 (you have more coding to prevent it)
sometimes you will not be able to leave textbox binded to numberic (int,dec) empty (blank), unless you enter a value (you have more coding to allow it)
binding is powerful and easy if used with dataset, but not easy if used with LinqToSql or EF
In my form, I use binding and manual where necessary.
|
|
|
|
|
Samir Ibrahim wrote: If you bind a control (textbox) to datasource (access or mssql) to field ID (AutoNumber) and you want to add new record, the textbox will display -1 (you have more coding to prevent it) Never show the autoId to a user. If you need an ID for the user, add a column for it, but don't use the PK.
Binding is cheap.
Bastard Programmer from Hell
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
>> add a column for it, but don't use the PK.
That will require creating another table to handle the numbering for your application plus coding to handle the incremented value in that column, well, simply, I don't bind the PK, I handle it manually.
|
|
|
|
|
I've come to realize there's no point in binding the autonumber/PK because, at most, it's only used for display. It's not something the user can edit. I display it in a label, using "New" when it's -1.
|
|
|
|
|
>>at most, it's only used for display. It's not something the user can edit. I display it in a label
It can be used for entering a number to search for, so I don't bind the PK to a textbox, I handle it manually.
|
|
|
|
|
|
Hello,
I've been working with this batch file for a few hours and I can't seem to get this file to work properly and I can't use PowerShell because my company's network won't allow it so I'm using a batch file. I'm trying to go through a list of machines and I can't seem to get past the first machine. I think I found the issue though but can't seem to get the line fixed to go to the second machine. I think it's after the findstr line after troubleshooting the code line by line.
Here's my code of what I tried.
""
@echo off
For /f %%i in (C:\Users\%username%\desktop\computers.txt) do (
echo %DATE% %TIME%
echo.
Echo ************************
Echo %%i
Echo ************************
:name
ping %%i /n 1 | find "Reply from %%i:"
if errorlevel 0 echo The computer is online and on VPN
if errorlevel 1 echo The computer is offline or not on VPN
if errorlevel 1 goto skip
REG QUERY "\\%%i\regpath" | findstr "Computer"
query user /server:%%i
dir /T:W "\\%%i\C$\path\file.exe" | find "exe"
(findstr /i /l "configurationserver=https://URL" \\%%i\C$\path\file.ini > NUL && (goto skip) || goto fixfile)
:FIXFILE
echo pfile.ini isn't good
code to fix issue
:SKIP
echo file is good
)
pause
""
for testing purposes the computers.txt has two computer IP Addresses
%IPADDRESS%
%IPADDRESS%
I've tried errorlevel for the findstr and also the second solution within the code.
modified 19-Nov-21 21:01pm.
|
|
|
|
|
It's impossible to test your script, but I will say if FINDSTR finds the string in the file, ERRORLEVEL will be 0. If not found, or the file does not exist, ERRORLEVEL will be 1.
When you check for ERRORLEVEL in a block of IF statements, you have to check for the highest possible errorlevel value first and check for 0 last. This is because the IF ERRORLEVEL will return true if ERRORLEVEL is greater than or equal to the specified value. So if you check for 0 first, the result will always be true, no matter what the value of ERRORLEVEL is.
Remove the ECHO's from your IF statements and just jump to a block that contains the ECHO statements and what to do after that. This will eliminate the need for multiple IF statements checking for the same ERRORLEVEL.
|
|
|
|
|
I have a requirement to display a shutdown message (using the InitiateSystemShutdownExW API) from a service, but using the interactive user's language.
The GetUserDefaultLCID looks like it should do what I want, but it doesn't. I assume that is because my service is not running in the interactive user's context. It instead returns the "install language" for the system.
Is there a way to programmatically retrieve the interactive user's language (e.g. using the remote session API)?
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
Hi Daniel,
I think you are asking if it's possible to use the GetUserDefaultLCID function by impersonating the security context of a logged-on user. But I'm not sure if you know what that means. For example User1 (or Administrator) can execute apps as User2 and User3 which means all those user accounts will have 'interactive sessions'.
Also... you need to clarify which user language[^] you want to use. For example, some users might have MUI enabled[^] and have both Hebrew and English (or maybe a dozen).
If you really do want to look up the same information that the GetUserDefaultLCID function retrieves for a user that logged in via winlogon.exe from your system service then I can help you do that.
#pragma comment(lib, "Secur32.lib")
#pragma comment(lib, "Advapi32.lib")
#include <iostream>
#include <windows.h>
#include <ntsecapi.h>
#include <sddl.h>
BOOL RegGetInternationaliations(const PSID p, const wchar_t name[], wchar_t *pOut, DWORD out_len)
{
LPWSTR szSid = nullptr;
BOOL bRet = FALSE;
if (ConvertSidToStringSidW(p, &szSid))
{
HKEY k;
constexpr DWORD size = 256;
WCHAR buffer[size];
wsprintf(buffer, L"%s\\Control Panel\\International", szSid);
LSTATUS status = RegOpenKeyW(HKEY_USERS, buffer, &k);
if (ERROR_SUCCESS == status)
{
status = RegGetValueW(k, NULL, name, RRF_RT_REG_SZ | RRF_ZEROONFAILURE, 0, pOut, &out_len);
bRet = (ERROR_SUCCESS == status);
RegCloseKey(k);
}
LocalFree(szSid);
}
return bRet;
}
INT main()
{
DWORD lc = 0;
DWORD status = 0;
PLUID list = nullptr;
LsaEnumerateLogonSessions(&lc, &list);
for (DWORD i = 0; i < lc; i++)
{
PSECURITY_LOGON_SESSION_DATA pData;
status = LsaGetLogonSessionData((PLUID)((INT_PTR)list + sizeof(LUID) * i), &pData);
if (0 == status)
{
if (Interactive == pData->LogonType && (pData->UserFlags & LOGON_WINLOGON))
{
constexpr DWORD s = 256;
WCHAR buffer[s];
if (RegGetInternationaliations(pData->Sid, L"Locale", buffer, s))
{
wprintf(L"Locale: %s\n", buffer);
}
}
LsaFreeReturnBuffer(pData);
}
}
}
This will work from session 0 and does exactly the same thing as the GetUserDefaultLCID function for the logged in users. Those internationalization registry keys have been pretty much unchanged for 14 years (I think the last change there was 2006)
If you really do want to do this for ALL interactive sessions then remove the following:
if (Interactive == pData->LogonType && (pData->UserFlags & LOGON_WINLOGON))
Also... if this isn't what you wanted... and what you really wanted was the currently selected MUI language[^] then let me know, it's an easy change.
I'm getting off now so I won't be back until tomorrow to read your response.
Best Wishes,
-David Delaune
|
|
|
|
|
Thank you. This is almost what I need, which is the logged-on user's currently selected display language. Please post the modification when you can...
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
Hi Daniel,
See if something like this would work for you:
BOOL RegGetPreferredUILanguages(const PSID p, std::vector<std::wstring>& out_vector)
{
LPWSTR szSid = nullptr;
BOOL bRet = FALSE;
if (ConvertSidToStringSidW(p, &szSid))
{
HKEY k;
constexpr DWORD size = 256;
WCHAR buffer[size];
wsprintf(buffer, L"%s\\Control Panel\\Desktop", szSid);
LSTATUS status = RegOpenKeyW(HKEY_USERS, buffer, &k);
if (ERROR_SUCCESS == status)
{
DWORD dwNeeded = 0;
std::vector<WCHAR> multi_sz;
RegGetValue(k, nullptr, L"PreferredUILanguages", RRF_RT_REG_MULTI_SZ, nullptr, nullptr, &dwNeeded);
multi_sz.resize(dwNeeded / sizeof(WCHAR));
if (ERROR_SUCCESS == RegGetValue(k, nullptr, L"PreferredUILanguages", RRF_RT_REG_MULTI_SZ | RRF_ZEROONFAILURE, nullptr, &multi_sz[0], &dwNeeded))
{
std::wistringstream ss(std::wstring(multi_sz.begin(), multi_sz.end()));
std::wstring lang;
while (std::getline(ss, lang, L'\0'))
{
if(lang.length())
out_vector.push_back(lang);
}
bRet = TRUE;
}
RegCloseKey(k);
}
LocalFree(szSid);
}
return bRet;
}
You would use it something like this:
std::vector<std::wstring> langs;
RegGetPreferredUILanguages(pData->Sid, langs);
UINT index = 1;
for (auto lang : langs)
{
wprintf(L"User Preferred UI Language at index %u is: %s \n", index++, lang.c_str());
}
My understanding is that the first entry is the current preferred UI language.
I have some additional comments:
1.) If you are doing this in a corporate environment then you might want to check for the domain/machine policy[^] first. The security policy is located in the registry at HKLM\Software\Policies\Microsoft\MUI\Settings and you would need to honor that.
2.) You will need to use a multi-tiered fallback. The HKCU\Control Panel\Desktop\PreferredUILanguages key will not exist if the user has not setup MUI and a default language. I believe you need fallback in this order:
* HKCU\Control Panel\Desktop\PreferredUILanguages (User prference) **might not be present**
* HKCU\Control Panel\Control Panel\International\Locale (User default) **always present**
* HKLM\SYSTEM\CurrentControlSet\Control\MUI\Settings\PreferredUILanguages (MUI default) **might not be present**
* HKLM\SYSTEM\CurrentControlSet\Control\Nls\Language\Default **always present**
* HKLM\SYSTEM\CurrentControlSet\Control\Nls\Language\InstallLanguage **always present**
The MUI keys are only present if the user has enabled MUI and installed multiple language packs. You can convert from LCID to locale with the LCIDToLocaleName function[^]. And use the LocaleNameToLCID function[^] for the reverse.
Here is how you would use them: (with the provided sample code)
constexpr DWORD s = 256;
WCHAR buffer[s] = {0};
WCHAR name[LOCALE_NAME_MAX_LENGTH] = {0};
if (RegGetInternationaliations(pData->Sid, L"Locale", buffer, s))
{
wprintf(L"Default User Hex locale: %s\n", buffer);
DWORD id = wcstol(buffer, NULL, 16);
wprintf(L"Default User Dec locale: %u\n", id);
LCIDToLocaleName(id, name, LOCALE_NAME_MAX_LENGTH, LOCALE_ALLOW_NEUTRAL_NAMES);
wprintf(L"Default User Locale Name: %s\n", name);
}
Let me know if this works out for you.
Best Wishes,
-David Delaune
|
|
|
|
|
Hi David,
Thank you very much for this lucid explanation of the MUI Registry info. and how to extract it. I'm sure that I'll be able to build something that serves from this.
Whatever you did in the past or are doing at the moment, you have obviously mastered an arcane part of Windows programming. Thanks again.
Best Wishes,
Daniel Pfeffer
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
David,
Thank you again for this solution. It works perfectly, and enabled me to answer a client's request.
This is a work project, so I can't for obvious reasons, share it with you, but if Legal at work permits, would you mind my using my version of the code as a basis for a short CodeProject article?
I would, of course, give you full credit for this solution.
Thanks again,
Daniel
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
Hello Daniel,
I apologize for the slow response. I haven't been on codeproject.com in a few weeks.
All of the sample code that I have written here in this forum is now in the public domain. You may use, modify and share it without restriction. Attribution is unnecessary. Keep in mind that it is a code sample and there is no guarantee of completeness or accuracy.
It looks like I am going to be mostly unavailable for the next few weeks. So I might not have much time for internet forums.. I should have more time in November.
Looking at the above code do see a potential political issue for your geo region. Make sure that you understand what "neutral names" implies with the LOCALE_ALLOW_NEUTRAL_NAMES flag. Or just remove it.
I also see a potential divide-by-zero surrounding the DWORD dwNeeded where the length comes from the registry, might want to add a if(dwNeeded) around that. It's an imperfect code sample, so you might want to polish it up a bit.
Best Wishes,
-David Delaune
|
|
|
|
|
Dear David,
Thanks for the release to public domain, for the warning of incompleteness, and especially for the warning re potential political issues - I never even considered the last... As I work for a multi-national (Western Digital), I wouldn't want my work banned in certain countries...
Best Regards,
Daniel Pfeffer
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
I am developing a service for a client, and must display a system-modal message box from the service. I would like my message box to look similar to other notifications displayed by the system (e.g. low power notifications, Windows Update notifications, etc.)
I can display an message box from the service in the standard Windows format. Is there an API to display windows in this format, or must I write it myself?
Thanks.
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
There is no System Modal anymore, so you will have to find some other way of doing what you want. Take a look at Security Blackout Window[^] which may be of use, or provide ideas.
|
|
|
|
|
Thanks, this looks like what I need.
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
When I search on the Internet, I find millions of web pages explaining how to check if a .exe-file is running, from within a .bat-file. However, I can't find a single page explaining what to do if you have several .exe-files with identical names and you only want to check an .exe-file that resides in a specific folder. Can anybody please help me, what's the way to detect if the file C:\MyProject\bin\release\MyApplication.exe is running, but at the same time completely ignore C:\MyProject\bin\debug\MyApplication.exe?
|
|
|
|
|
|
Victor Nijegorodov wrote: BTW, what do you mean by "... from within a .bat-file."? I want to do it in bat-file language (the language you type in the command prompt C:\Windows\System32\cmd.exe)
|
|
|
|
|
@echo off
set "workdir=C:\MyProject\bin\release"
set "workdir=%workdir:\=\\%"
setlocal enableDelayedExpansion
for /f "usebackq tokens=* delims=" %%a in (`
wmic process where 'CommandLine like "%%!workdir!%%" and not CommandLine like "%%RuntimeBroker%%"' get CommandLine^,ProcessId /format:value
`) do (
for /f "tokens=* delims=" %%G in ("%%a") do (
if "%%G" neq "" (
rem echo %%G
set "%%G"
rem echo !ProcessId!
goto :TheApplicationIsRunning
)
)
)
echo The application is not running
exit /B
:TheApplicationIsRunning
echo The application is running
exit /B
|
|
|
|
|