Skip to content

Commit

Permalink
Add a spec for #7335, "console allocation policy" (#7337)
Browse files Browse the repository at this point in the history
This is a specification for a way to customize console allocations.
The new manifest type `consoleAllocationPolicy` and the new
`AllocConsoleWithOptions` API were already added to the console
client library internally.

Closes #7335
  • Loading branch information
DHowett authored Feb 7, 2024
1 parent 71efdcb commit 71c35cf
Show file tree
Hide file tree
Showing 4 changed files with 406 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .github/actions/spelling/allow/allow.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ CMMI
copyable
Counterintuitively
CtrlDToClose
CUI
cybersecurity
dalet
Dcs
Expand Down Expand Up @@ -80,11 +81,13 @@ noreply
ogonek
ok'd
overlined
perlw
pipeline
postmodern
Powerline
powerline
ptys
pwshw
qof
qps
rclt
Expand All @@ -93,6 +96,7 @@ reserialization
reserialize
reserializes
rlig
rubyw
runtimes
servicebus
shcha
Expand All @@ -113,6 +117,7 @@ toolset
truthiness
tshe
ubuntu
UEFI
uiatextrange
UIs
und
Expand Down
2 changes: 2 additions & 0 deletions .github/actions/spelling/allow/apis.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ acl
aclapi
alignas
alignof
allocconsolewithoptions
APPLYTOSUBMENUS
appxrecipe
bitfield
Expand Down Expand Up @@ -156,6 +157,7 @@ OUTLINETEXTMETRICW
overridable
PACL
PAGESCROLL
PALLOC
PATINVERT
PEXPLICIT
PICKFOLDERS
Expand Down
3 changes: 3 additions & 0 deletions .github/actions/spelling/allow/microsoft.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ cpptools
cppvsdbg
CPRs
cryptbase
cscript
DACL
DACLs
defaultlib
Expand Down Expand Up @@ -88,8 +89,10 @@ Virtualization
visualstudio
vscode
VSTHRD
WINBASEAPI
winsdkver
wlk
wscript
wslpath
wtl
wtt
Expand Down
Loading

4 comments on commit 71c35cf

@rbeesley
Copy link
Contributor

@rbeesley rbeesley commented on 71c35cf Nov 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DHowett , big fan of this change and there is external incentive as well as can be seen on this StackOverflow thread. How do I know, because I just worked through this myself. I'm working on a Direct3D project, which in debug mode it sends some logs to a console window. It first tries to find the parent console window and attach to that, or if it is missing it allocates a new one. I eventually have settled on using a cli wrapper which creates a process to load the gui, following the python/pythonw sort of method, rather than having otherwise identical builds with only the /SUBSYSTEM flag changing.

#include <windows.h>
#include <iostream>

int main(const int argc, char* argv[]) {
    UNREFERENCED_PARAMETER(argc);
    UNREFERENCED_PARAMETER(argv);

    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));

    // Command line to launch hw3dw.exe
    wchar_t cmdLine[] = L"hw3dw.exe";

    // Start the child process.
    if (!CreateProcess(
        nullptr,        // No module name (use command line)
        cmdLine,        // Command line
        nullptr,        // Process handle not inheritable
        nullptr,        // Thread handle not inheritable
        FALSE,          // Set handle inheritance to FALSE
        0,              // No creation flags
        nullptr,        // Use parent's environment block
        nullptr,        // Use parent's starting directory
        &si,            // Pointer to STARTUPINFO structure
        &pi)            // Pointer to PROCESS_INFORMATION structure
        )
    {
        std::cerr << "CreateProcess failed (" << GetLastError() << ").\n";
        return -1;
    }

    // Wait until child process exits.
    WaitForSingleObject(pi.hProcess, INFINITE);

    // Close process and thread handles.
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    return 0;
}

It works, but it is also fragile because there is a need to keep both of these files together on the file system.

There is a caveat in the spec which should be considered. In my example, I'm trying to change this behavior based on different build targets, whether or not I'm making a release or debug build. Being able to change the manifest per build target should not be ignored as a possibility. For the release build, I'd want the behavior to exist as it does today and it is only the debug builds where I'd want to attach to the console without starting detached and returning control to the shell.

@lhecker
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a caveat in the spec which should be considered. [...] Being able to change the manifest per build target should not be ignored as a possibility. [...]

But nothing prevents you from having 2 manifests in your source tree and picking one for debug and the other for release builds. Or did I misunderstand what you're trying to achieve?

@rbeesley
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lhecker, you might be right. I've not used the manifest before and made an assumption that this would be generated by VS. Even so, this is an implementation detail and not part of the spec, so this isn't really a concern and easily resolved. I'd prefer it if there was a simple way to apply this specific delta to the same manifest per build, but again that's an implementation detail and not part of this spec. Good call.

@lhecker
Copy link
Member

@lhecker lhecker commented on 71c35cf Nov 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've not used the manifest before and made an assumption that this would be generated by VS

VS can indeed generate the manifest for you or change it according to your build settings, but it only includes some of the most basic ones (e.g. whether you want to launch as admin). I'm not sure if you're doing this already, but generally speaking, I can recommend writing your own manifest file. For instance, I recently wrote this one for one of my apps:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly
    xmlns="urn:schemas-microsoft-com:asm.v1"
    xmlns:asm3="urn:schemas-microsoft-com:asm.v3"
    xmlns:cv1="urn:schemas-microsoft-com:compatibility.v1"
    xmlns:ws="http://schemas.microsoft.com/SMI/2005/WindowsSettings"
    xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings"
    xmlns:ws3="http://schemas.microsoft.com/SMI/2019/WindowsSettings"
    manifestVersion="1.0">
    <asm3:application>
        <windowsSettings>
            <ws:dpiAware>true</ws:dpiAware>
            <ws2:dpiAwareness>PerMonitorV2</ws2:dpiAwareness>
            <ws2:longPathAware>true</ws2:longPathAware>
            <ws3:activeCodePage>UTF-8</ws3:activeCodePage>
        </windowsSettings>
    </asm3:application>
    <cv1:compatibility>
        <application>
            <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
        </application>
    </cv1:compatibility>
    <dependency>
        <dependentAssembly>
            <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*" />
        </dependentAssembly>
    </dependency>
</assembly>
  • Enables per-monitor DPI awareness (the first two settings)
  • Enables long-path support
  • Enables using UTF8 by default across all A style APIs and those that are locale-aware
  • Declares compatibility with Windows 10/11 (that's the GUID, all older versions are excluded)
  • Declares that it wants the modern ComCtl UI look (the last setting at the end, only needed because I use ComCtl for that app)

To build with that manifest, simply include it as a file in your solution explorer as if it was any other source file. The linker will take care of it. To change between Debug/Release, you can include 2 different manifest files, right-click on them, open the "Properties" dialog, and then change the "Excluded From Build" setting (= exclude one of them from all Debug configurations, and the other from all Release ones).

Please sign in to comment.