jjzjj

c# - 如何在 C# 和 Windows 7 中设置音量?

coder 2024-06-05 原文

我想在 winforms 中将系统音量设置为 65%。有没有我可以导入和使用的 dll?

我试过了

public partial class Form1 : Form
{
    private const int APPCOMMAND_VOLUME_MUTE = 0x80000;
    private const int APPCOMMAND_VOLUME_UP = 0xA0000;
    private const int APPCOMMAND_VOLUME_DOWN = 0x90000;
    private const int WM_APPCOMMAND = 0x319;

    [DllImport("user32.dll")]
    public static extern IntPtr SendMessageW(IntPtr hWnd, int Msg,
    IntPtr wParam, IntPtr lParam);

    public Form1()
    {
        InitializeComponent();
    }

    private void btnDecVol_Click(object sender, EventArgs e)
    {
        SendMessageW(this.Handle, WM_APPCOMMAND, this.Handle,
        (IntPtr)APPCOMMAND_VOLUME_DOWN);
    }

    private void btnIncVol_Click(object sender, EventArgs e)
    {
        SendMessageW(this.Handle, WM_APPCOMMAND, this.Handle,
        (IntPtr)APPCOMMAND_VOLUME_UP);
    }

    static class NativeMethods
    {
        [DllImport("winmm.dll", EntryPoint = "waveOutSetVolume")]
        public static extern int WaveOutSetVolume(IntPtr hwo, uint dwVolume);
    }
}

但在这个我可以增加或减少不能设置一个完美的值。我的问题可能与 this 重复但不再支持问题的答案,因为支持的链接已删除,其他支持的链接仅提供详细的教程,这本身就是一项很好的研究。

最佳答案

请尝试以下操作:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var v = AudioMixerHelper.GetVolume(0x2, 0x4);

            AudioMixerHelper.SetVolume(0x2, 0x4, 140);
        }
    }




    class AudioMixerHelper
    {
       // This is the only error code we will use
        public const int MMSYSERR_NOERROR = 0;

        //-------------------------------------------------------------------

        public const int MAXPNAMELEN = 32;

        public const int MIXER_SHORT_NAME_CHARS = 16;
        public const int MIXER_LONG_NAME_CHARS = 64;

        public const int MIXER_GETLINECONTROLSF_ONEBYTYPE = 2;
        public const int MIXER_GETLINEINFOF_COMPONENTTYPE = 3;

        public const int MIXER_GETCONTROLDETAILSF_VALUE = 0;
        public const int MIXER_SETCONTROLDETAILSF_VALUE = 0;

        //-------------------------------------------------------------------

        public const int MIXERCONTROL_CT_CLASS_SWITCH = 0x20000000;
        public const int MIXERCONTROL_CT_CLASS_FADER = 0x50000000;

        public const int MIXERCONTROL_CT_UNITS_BOOLEAN = 0x10000;
        public const int MIXERCONTROL_CT_UNITS_UNSIGNED = 0x30000;

        //-------------------------------------------------------------------

        public const int MIXERCONTROL_CONTROLTYPE_FADER =
            (MIXERCONTROL_CT_CLASS_FADER | MIXERCONTROL_CT_UNITS_UNSIGNED);

        public const int MIXERCONTROL_CONTROLTYPE_VOLUME =
            (MIXERCONTROL_CONTROLTYPE_FADER + 1);

        public const int MIXERCONTROL_CONTROLTYPE_BOOLEAN =
            (MIXERCONTROL_CT_CLASS_SWITCH | MIXERCONTROL_CT_UNITS_BOOLEAN);

        public const int MIXERCONTROL_CONTROLTYPE_MUTE =
            (MIXERCONTROL_CONTROLTYPE_BOOLEAN + 2);

        //-------------------------------------------------------------------

        // SRC COMPONENT TYPE
        public const int MIXERLINE_COMPONENTTYPE_SRC_FIRST = 0x1000;

        public const int MIXERLINE_COMPONENTTYPE_SRC_LINE =
            (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 2);

        //-------------------------------------------------------------------

        // DST COMPONENT TYPE
        public const int MIXERLINE_COMPONENTTYPE_DST_SPEAKERS = 4;

        //-------------------------------------------------------------------

        // This is the callback notification which we use for synchronization
        public const int MM_MIXM_CONTROL_CHANGE = 0x3D1;

        //-------------------------------------------------------------------

        // This is the parameter used to enable .._CONTROL_CHANGE notifications
        public const int CALLBACK_WINDOW = 0x10000;

        //-------------------------------------------------------------------

        [DllImport("winmm.dll", CharSet = CharSet.Ansi)]                                                    // mixerOpen
        private static extern int mixerOpen(
                                        out int phmx,
                                        int uMxId,
                                        int dwCallback,
                                        int dwInstance,
                                        int fdwOpen);

        [DllImport("winmm.dll", CharSet = CharSet.Ansi)]                                                    // mixerClose
        private static extern int mixerClose(int hmx);

        [DllImport("winmm.dll", CharSet = CharSet.Ansi)]                                                    // mixerGetControlDetailsA
        private static extern int mixerGetControlDetailsA(
                                            int hmxobj,
                                            ref MIXERCONTROLDETAILS pmxcd,
                                            int fdwDetails);

        [DllImport("winmm.dll", CharSet = CharSet.Ansi)]                                                    // mixerGetLineControlsA
        private static extern int mixerGetLineControlsA(
                                            int hmxobj,
                                            ref MIXERLINECONTROLS pmxlc,
                                            int fdwControls);

        [DllImport("winmm.dll", CharSet = CharSet.Ansi)]                                                    // mixerGetLineInfoA
        private static extern int mixerGetLineInfoA(
                                            int hmxobj,
                                            ref MIXERLINE pmxl,
                                            int fdwInfo);

        [DllImport("winmm.dll", CharSet = CharSet.Ansi)]                                                    // mixerSetControlDetails
        private static extern int mixerSetControlDetails(
                                            int hmxobj,
                                            ref MIXERCONTROLDETAILS pmxcd,
                                            int fdwDetails);

        // -----------------------------------------------------------------------

        public struct MIXERCONTROL                                                                          // MIXERCONTROL
        {
            public int cbStruct;                    // Size in bytes of MIXERCONTROL
            public int dwControlID;                 // Unique control ID for mixer device
            public int dwControlType;               // MIXERCONTROL_CONTROLTYPE_xxx
            public int fdwControl;                  // MIXERCONTROL_CONTROLF_xxx
            public int cMultipleItems;              // If MIXERCONTROL_CONTROLF_MULTIPLE set

            [MarshalAs(UnmanagedType.ByValTStr,
            SizeConst = MIXER_SHORT_NAME_CHARS)]
            public string szShortName;              // Short name of control

            [MarshalAs(UnmanagedType.ByValTStr,
            SizeConst = MIXER_LONG_NAME_CHARS)]
            public string szName;                   // Long name of control

            public int lMinimum;                    // Minimum value
            public int lMaximum;                    // Maximum value

            [MarshalAs(UnmanagedType.U4,
            SizeConst = 10)]
            public int reserved;
        }

        public struct MIXERCONTROLDETAILS                                                                   // MIXERCONTROLDETAILS
        {
            public int cbStruct;                    // Size in bytes of MIXERCONTROLDETAILS
            public int dwControlID;                 // Control ID to get/set details on
            public int cChannels;                   // Number of channels in paDetails array
            public int item;                        // hwndOwner or cMultipleItems
            public int cbDetails;                   // Size of _one_details_XX struct
            public IntPtr paDetails;                // Pointer to array of details_XX_struct
        }

        public struct MIXERCONTROLDETAILS_UNSIGNED                                                          // MIXERCONTROLDETAILS_UNSIGNED
        {
            public int dwValue;
        }

        public struct MIXERLINE                                                                             // MIXERLINE
        {
            public int cbStruct;                    // Size of MIXERLINE struct
            public int dwDestination;               // Zero based destination index
            public int dwSource;                    // Zero based source index (if source)
            public int dwLineID;                    // Unique line ID for mixer device
            public int fdwLine;                     // State/information about line
            public int dwUser;                      // Driver specific information
            public int dwComponentType;             // Component type line connects to
            public int cChannels;                   // Number of channels line supports
            public int cConnections;                // Number of possible connections
            public int cControls;                   // Number of controls belonging to this line

            [MarshalAs(UnmanagedType.ByValTStr,
            SizeConst = MIXER_SHORT_NAME_CHARS)]
            public string szShortName;              // Short name of control

            [MarshalAs(UnmanagedType.ByValTStr,
            SizeConst = MIXER_LONG_NAME_CHARS)]
            public string szName;                   // Long name of control

            public int dwType;
            public int dwDeviceID;
            public int wMid;                        // Manufacturer ID                        
            public int wPid;                        // Product ID
            public int vDriverVersion;              // Driver Vers. No.

            [MarshalAs(UnmanagedType.ByValTStr,
            SizeConst = MAXPNAMELEN)]
            public string szPname;                  // Product name
        }

        public struct MIXERLINECONTROLS                                                                     // MIXERLINECONTROLS
        {
            public int cbStruct;                    // Size in bytes of MIXERLINECONTROLS
            public int dwLineID;                    // Line ID (from MIXERLINE.dwLineID)
            // MIXER_GETLINECONTROLSF_ONEBYID or
            public int dwControl;                   // MIXER_GETLINECONTROLSF_ONEBYTYPE
            public int cControls;                   // Number of controls pamxctrl points to
            public int cbmxctrl;                    // Size in bytes of _one_ MIXERCONTROL
            public IntPtr pamxctrl;                 // Pointer to first MIXERCONTROL array
        }

        // This function attempts to obtain a specified mixer control/component pair - 
        // returns true if successful.
        private static bool GetMixerControl(                                                                // GetMixerControl
                                        int hmixer,
                                        int component,
                                        int control,
                                        out MIXERCONTROL mxc,
                                        out int vCurrentVol)
        {
            bool retValue = false;
            mxc = new MIXERCONTROL();

            MIXERLINECONTROLS mxlc = new MIXERLINECONTROLS();
            MIXERLINE mxl = new MIXERLINE();
            MIXERCONTROLDETAILS pmxcd = new MIXERCONTROLDETAILS();
            MIXERCONTROLDETAILS_UNSIGNED du = new MIXERCONTROLDETAILS_UNSIGNED();

            vCurrentVol = -1;       // A dummy value

            mxl.cbStruct = Marshal.SizeOf(mxl);
            mxl.dwComponentType = component;

            int rc = mixerGetLineInfoA(
                                hmixer,
                                ref mxl,
                                MIXER_GETLINEINFOF_COMPONENTTYPE);

            if (MMSYSERR_NOERROR == rc)
            {
                int sizeofMIXERCONTROL = 152;
                int ctrl = Marshal.SizeOf(typeof(MIXERCONTROL));
                mxlc.pamxctrl = Marshal.AllocCoTaskMem(sizeofMIXERCONTROL);
                mxlc.cbStruct = Marshal.SizeOf(mxlc);
                mxlc.dwLineID = mxl.dwLineID;
                mxlc.dwControl = control;
                mxlc.cControls = 1;
                mxlc.cbmxctrl = sizeofMIXERCONTROL;

                // Allocate a buffer for the control 
                mxc.cbStruct = sizeofMIXERCONTROL;

                // Get the control 
                rc = mixerGetLineControlsA(
                                        hmixer,
                                        ref mxlc,
                                        MIXER_GETLINECONTROLSF_ONEBYTYPE);

                if (MMSYSERR_NOERROR == rc)
                {
                    retValue = true;
                    // Copy the control into the destination structure 
                    mxc = (MIXERCONTROL)Marshal.PtrToStructure(
                                                            mxlc.pamxctrl,
                                                            typeof(MIXERCONTROL));
                }

                int sizeofMIXERCONTROLDETAILS =
                    Marshal.SizeOf(typeof(MIXERCONTROLDETAILS));

                int sizeofMIXERCONTROLDETAILS_UNSIGNED =
                    Marshal.SizeOf(typeof(MIXERCONTROLDETAILS_UNSIGNED));

                pmxcd.cbStruct = sizeofMIXERCONTROLDETAILS;
                pmxcd.dwControlID = mxc.dwControlID;
                pmxcd.paDetails = Marshal.AllocCoTaskMem(sizeofMIXERCONTROLDETAILS_UNSIGNED);
                pmxcd.cChannels = 1;
                pmxcd.item = 0;
                pmxcd.cbDetails = sizeofMIXERCONTROLDETAILS_UNSIGNED;

                rc = mixerGetControlDetailsA(
                                    hmixer,
                                    ref pmxcd,
                                    MIXER_GETCONTROLDETAILSF_VALUE);

                du = (MIXERCONTROLDETAILS_UNSIGNED)Marshal.PtrToStructure(
                                                            pmxcd.paDetails,
                                                            typeof(MIXERCONTROLDETAILS_UNSIGNED));

                vCurrentVol = du.dwValue;

                return retValue;    // true
            }

            return retValue;        // false
        }

        private static bool SetVolumeControl(                                                               // SetVolumeControl
                                    int hmixer,
                                    MIXERCONTROL mxc,
                                    int volume)
        {
            bool retValue = false;
            int rc;

            MIXERCONTROLDETAILS mxcd = new MIXERCONTROLDETAILS();
            MIXERCONTROLDETAILS_UNSIGNED vol = new MIXERCONTROLDETAILS_UNSIGNED();

            mxcd.item = 0;
            mxcd.dwControlID = mxc.dwControlID;
            mxcd.cbStruct = Marshal.SizeOf(mxcd);
            mxcd.cbDetails = Marshal.SizeOf(vol);

            // Allocate a buffer for the control value buffer 
            mxcd.cChannels = 1;
            vol.dwValue = volume;

            // Copy the data into the control value buffer 
            mxcd.paDetails = Marshal.AllocCoTaskMem(
                                Marshal.SizeOf(typeof(MIXERCONTROLDETAILS_UNSIGNED)));

            Marshal.StructureToPtr(
                                vol,
                                mxcd.paDetails,
                                false);

            // Set the control value 
            rc = mixerSetControlDetails(
                                    hmixer,
                                    ref mxcd,
                                    MIXER_SETCONTROLDETAILSF_VALUE);

            return retValue = MMSYSERR_NOERROR == rc ? true : false;
        }

        public static int GetVolume(int control, int component)                                             // GetVolume
        {
            int hmixer = 0;
            int currVol = -1;

            MIXERCONTROL volCtrl = new MIXERCONTROL();

            int rc = mixerOpen(
                            out hmixer,
                            0,
                            0,
                            0,
                            0);

            bool b = GetMixerControl(
                                hmixer,
                                component,
                                control,
                                out volCtrl,        // Not used
                                out currVol);

            mixerClose(hmixer);

            return currVol;
        }

        public static void SetVolume(int control, int component, int newVol)                              // SetVolume
        {
            int hmixer = 0;
            int currentVol;

            MIXERCONTROL volCtrl = new MIXERCONTROL();

            mixerOpen(
                    out hmixer,
                    0,
                    0,
                    0,
                    0);

            GetMixerControl(
                        hmixer,
                        component,
                        control,
                        out volCtrl,
                        out currentVol);            // Not used

            SetVolumeControl(hmixer, volCtrl, newVol);

            mixerClose(hmixer);
        }

        public static bool MonitorControl(int iw)     // iw is the window handle                          // MonitorControl
        {
            int rc = -1;
            bool retValue = false;

            int hmixer;
            rc = mixerOpen(
                        out hmixer,
                        0,
                        iw,
                        0,
                        CALLBACK_WINDOW);

            return retValue = (MMSYSERR_NOERROR == rc) ? true : false;
        }

        public static int CheckMixer()                                                                      // CheckMixer
        {
            int retValue = -1;
            int rc1, rc2 = -1;
            int hmixer;

            rc1 = mixerOpen(
                        out hmixer,
                        0,
                        0,
                        0,
                        0);

            rc2 = mixerClose(hmixer);

            return retValue = (MMSYSERR_NOERROR == rc1) && (MMSYSERR_NOERROR == rc2) ? MMSYSERR_NOERROR : retValue;
        }

        public static int GetControlID(int component, int control)                                        // GetControlID
        {
            MIXERCONTROL mxc = new MIXERCONTROL();
            int _i;         // Though we won't need _i, it still must be declared                                    

            bool b = false;
            int retValue = 0;

            b = GetMixerControl(
                            0,
                            component,
                            control,
                            out mxc,
                            out _i);

            return retValue = b ? mxc.dwControlID : -1;
        }

    }
}

如果这仍然不起作用,请尝试 Naudio ( https://naudio.codeplex.com/ ) 并按如下方式调用:

public void SetVolume(int level)
   {
            try
            {
                //Instantiate an Enumerator to find audio devices
                    NAudio.CoreAudioApi.MMDeviceEnumerator MMDE = new NAudio.CoreAudioApi.MMDeviceEnumerator();
                        //Get all the devices, no matter what condition or status
                NAudio.CoreAudioApi.MMDeviceCollection DevCol = MMDE.EnumerateAudioEndPoints(NAudio.CoreAudioApi.DataFlow.All, NAudio.CoreAudioApi.DeviceState.All);
                //Loop through all devices
                foreach (NAudio.CoreAudioApi.MMDevice dev in DevCol)
                {
                    try
                    {
                        if (dev.State == NAudio.CoreAudioApi.DeviceState.Active)
                        {
                            var newVolume = (float)Math.Max(Math.Min(level, 100),0) / (float)100;

                            //Set at maximum volume
                            dev.AudioEndpointVolume.MasterVolumeLevelScalar = newVolume;

                            dev.AudioEndpointVolume.Mute = level == 0;

                            //Get its audio volume
                            _log.Info("Volume of " + dev.FriendlyName + " is " + dev.AudioEndpointVolume.MasterVolumeLevelScalar.ToString());
                        }
                        else
                        {
                            _log.Debug("Ignoring device " + dev.FriendlyName + " with state " + dev.State);
                        }
                    }
                    catch (Exception ex)
                    {
                        //Do something with exception when an audio endpoint could not be muted
                        _log.Warn(dev.FriendlyName + " could not be muted with error " + ex);
                    }
                }
            }
            catch (Exception ex)
            {
                //When something happend that prevent us to iterate through the devices
                _log.Warn("Could not enumerate devices due to an excepion: " + ex.Message);
            }
        }

关于c# - 如何在 C# 和 Windows 7 中设置音量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33169982/

有关c# - 如何在 C# 和 Windows 7 中设置音量?的更多相关文章

  1. ruby - 如何在 Ruby 中顺序创建 PI - 2

    出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits

  2. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  3. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  4. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  5. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  6. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  7. ruby - 如何在 Ruby 中拆分参数字符串 Bash 样式? - 2

    我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"

  8. ruby - 如何在 Lion 上安装 Xcode 4.6,需要用 RVM 升级 ruby - 2

    我实际上是在尝试使用RVM在我的OSX10.7.5上更新ruby,并在输入以下命令后:rvminstallruby我得到了以下回复:Searchingforbinaryrubies,thismighttakesometime.Checkingrequirementsforosx.Installingrequirementsforosx.Updatingsystem.......Errorrunning'requirements_osx_brew_update_systemruby-2.0.0-p247',pleaseread/Users/username/.rvm/log/138121

  9. ruby-on-rails - 如何在 ruby​​ 交互式 shell 中有多行? - 2

    这可能是个愚蠢的问题。但是,我是一个新手......你怎么能在交互式ruby​​shell中有多行代码?好像你只能有一条长线。按回车键运行代码。无论如何我可以在不运行代码的情况下跳到下一行吗?再次抱歉,如果这是一个愚蠢的问题。谢谢。 最佳答案 这是一个例子:2.1.2:053>a=1=>12.1.2:054>b=2=>22.1.2:055>a+b=>32.1.2:056>ifa>b#Thecode‘if..."startsthedefinitionoftheconditionalstatement.2.1.2:057?>puts"f

  10. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

随机推荐